Lompat ke kandungan utama
8 minit bacaan

Muat naik gambar dengan CFML: had jenis fail, saiz dan nama selamat

Borang muat naik gambar kelihatan mudah, tetapi fail yang dihantar bukan milik kita. Tutorial ini memeriksa jenis dan saiz, mengesahkan fail itu benar-benar gambar, dan menyimpannya dengan nama yang selamat.

Coldfusion TutorialColdFusionCFMLKeselamatanPemula

Cuba contoh muat naik itu Boleh dicuba terus di laman ini. Gambar dipadam sendiri selepas 30 minit.

Muat turun kod penuh (fail zip) muat-naik.cfm + jadual.sql + arahan pemasangan

Ilustrasi empat langkah aliran muat naik gambar: borang, simpan sementara, periksa, kemudian simpan

Borang muat naik gambar kelihatan seperti kerja yang mudah. Pembaca memilih fail, tekan butang, gambar muncul. Tetapi fail yang dihantar datang dari komputer orang lain, dan ia bukan milik kita. Kalau kita menyimpan apa sahaja yang sampai tanpa diperiksa, kita membuka pintu kepada dua masalah, iaitu fail yang bukan gambar, dan fail gambar yang terlalu besar sehingga memenuhi ruang pelayan.

Tutorial ini membina satu halaman muat naik yang memeriksa empat perkara sebelum menyimpan apa-apa. Kodnya menggunakan teg asas CFML, iaitu cffile dan cfquery, supaya ia boleh diikuti oleh pemula. Contoh yang berjalan boleh dicuba di/demo/muat-naik.

Apa yang berlaku apabila gambar dihantar

Borang muat naik perlukan satu sifat yang mudah terlupa, iaitu enctype. Tanpa sifat itu, pelayar menghantar nama fail sahaja dan bukan kandungan fail. Apabila borang itu dihantar, teg cffile dengan tindakan upload mengambil fail itu dari permintaan dan menulisnya ke dalam folder pelayan.

<form action="/demo/muat-naik" method="post" enctype="multipart/form-data">
	<input type="file" name="gambar" accept="image/jpeg,image/png,image/webp">
	<button type="submit" name="hantar" value="1">Muat naik</button>
</form>

Di bahagian CFML, fail itu disimpan ke folder sementara, dan hasilnya diletakkan dalam satu struktur yang boleh kita periksa. Tiga nilai yang berguna ialah nama fail asal, folder simpanan, dan saiz fail.

<cffile action="upload" fileField="gambar" destination="#FOLDER#" nameConflict="MakeUnique" result="muat">

<cfoutput>
	Nama asal : #muat.clientFile#
	Folder    : #muat.serverDirectory#
	Saiz      : #int( muat.fileSize / 1024 )# KB
</cfoutput>
Nama fail yang datang bersama permintaan itu dihantar oleh pelayar pembaca. Ia boleh diubah dengan mudah, jadi ia sesuai untuk dipaparkan, tetapi tidak sekali-kali untuk menentukan nama fail yang kita simpan.

Empat pemeriksaan yang tidak boleh dilangkau

  • Sambungan fail mesti ada dalam senarai putih, iaitu jpg, jpeg, png atau webp. Jangan gunakan senarai hitam, kerana senarai itu sentiasa tertinggal sesuatu.
  • Saiz fail mesti di bawah had yang awak tetapkan. Di sini hadnya 2 MB, iaitu 2048 KB.
  • Kandungan fail mesti benar-benar gambar, bukan fail teks yang dinamakan semula.
  • Nama fail simpanan mesti dijana sendiri, bukan diambil daripada pembaca.

Pemeriksaan pertama dan kedua mudah difahami. Yang ketiga itulah yang sering dilangkau, dan ia yang paling penting. Menukar nama fail daripada nota.txt kepada gambar.jpg mengambil masa dua saat, dan pemeriksaan sambungan tidak akan mengesannya.

Memeriksa sama ada fail itu benar-benar gambar

Cara paling mudah dan paling kuat ialah meminta enjin CFML membuka fail itu sebagai gambar. Kalau ia berjaya membaca saiz gambar, fail itu memang gambar. Kalau ia gagal, fail itu ditolak, apa pun namanya. Dimensi yang diperoleh itu juga berguna untuk menghantar lebar dan tinggi kepada pelayar, supaya halaman tidak tersentak semasa gambar memuat.

<cfset lebar = 0>
<cfset tinggi = 0>
<cftry>
	<cfimage action="info" source="#muat.serverDirectory#/#muat.serverFile#" structName="info">
	<cfset lebar = info.width>
	<cfset tinggi = info.height>
	<cfcatch type="any">
		<cfset ralat = "Fail itu bukan gambar yang sah, walaupun namanya berakhir dengan .jpg.">
	</cfcatch>
</cftry>

Apabila mana-mana pemeriksaan gagal, jangan tinggalkan fail sementara itu di dalam folder. Padamkannya pada saat itu juga, kerana fail yang tertinggal akan terkumpul sehingga folder itu penuh.

<cfif not okMuat and fileExists( muat.serverDirectory & "/" & muat.serverFile )>
	<cftry><cfset fileDelete( muat.serverDirectory & "/" & muat.serverFile )><cfcatch></cfcatch></cftry>
</cfif>

Nama fail: jangan percaya nama daripada pembaca

Fail yang lulus pemeriksaan dinamakan semula sebelum disimpan. Nama baharu itu dijana oleh pelayan, dan sambungannya diambil daripada jenis yang kita benarkan. Dua masalah dapat dielakkan dengan cara ini, iaitu nama seperti ../../fail-penting.cfm tidak lagi berbahaya, dan dua pembaca yang memuat naik fail dengan nama sama tidak akan menimpa fail satu sama lain.

<cfset namaBaru = createUUID() & "." & ext>
<cfset fileMove( muat.serverDirectory & "/" & muat.serverFile, FOLDER & "/" & namaBaru )>

Menyimpan maklumat ke dalam jadual

Selepas fail selamat disimpan, satu baris direkod ke dalam jadual supaya halaman boleh memaparkan gambar itu. Gunakan cfqueryparam bagi setiap nilai, kerana ia yang memisahkan data daripada arahan SQL.

<cfquery name="qSimpan" datasource="#DS#">
	INSERT INTO demo_gambar ( nama_fail, nama_asal, jenis, saiz_kb, lebar, tinggi, ip_hash )
	VALUES (
		<cfqueryparam value="#namaBaru#" cfsqltype="cf_sql_varchar">,
		<cfqueryparam value="#muat.clientFile#" cfsqltype="cf_sql_varchar">,
		<cfqueryparam value="#ext#" cfsqltype="cf_sql_varchar">,
		<cfqueryparam value="#saizKb#" cfsqltype="cf_sql_integer">,
		<cfqueryparam value="#lebar#" cfsqltype="cf_sql_integer">,
		<cfqueryparam value="#tinggi#" cfsqltype="cf_sql_integer">,
		<cfqueryparam value="#ipHash#" cfsqltype="cf_sql_varchar">
	)
</cfquery>

Lajur ip_hash menyimpan cincangan alamat IP, bukan alamat itu sendiri. Ia digunakan untuk mengehadkan bilangan muat naik daripada satu sumber, dan pada masa yang sama ia tidak menyimpan maklumat peribadi pembaca dalam bentuk yang boleh dibaca.

Panjang lajur cincangan mesti sepadan dengan fungsi yang digunakan. SHA-256 menghasilkan 64 aksara, jadi lajur CHAR(40) akan menolak simpanan dengan ralat data too long. Periksa panjang itu semasa mencipta jadual, bukan selepas ia gagal.

Had dan pembersihan sendiri

Halaman yang boleh dicuba oleh sesiapa sahaja perlukan had, kerana ia akan dicuba oleh bot juga. Contoh ini memakai tiga had dan satu pembersihan automatik. Setiap kali halaman dibuka, fail dan baris yang berumur lebih daripada 30 minit dipadam sebelum apa-apa yang baharu diproses.

  • 10 muat naik sejam bagi setiap alamat IP.
  • 60 gambar dalam simpanan pada satu masa.
  • 2 MB bagi setiap fail.
  • Padam automatik selepas 30 minit, termasuk failnya di dalam folder.
<cfquery name="qTamat" datasource="#DS#">
	SELECT id, nama_fail FROM demo_gambar
	WHERE dicipta < DATE_SUB( NOW(), INTERVAL <cfqueryparam value="#HAD_SIMPAN_MINIT#" cfsqltype="cf_sql_integer"> MINUTE )
</cfquery>

<cfloop query="qTamat">
	<cfif fileExists( FOLDER & "/" & qTamat.nama_fail )>
		<cftry><cfset fileDelete( FOLDER & "/" & qTamat.nama_fail )><cfcatch></cfcatch></cftry>
	</cfif>
</cfloop>

Cara mengujinya

Ujian yang paling berguna bukan gambar yang cantik, tetapi kes yang sepatutnya ditolak. Empat ujian di bawah mengambil masa kurang daripada sepuluh minit, dan ia menunjukkan sama ada pemeriksaan itu benar-benar berfungsi.

  • Muat naik gambar PNG biasa. Ia sepatutnya berjaya, dan saiz sebenar muncul dalam senarai.
  • Cipta fail teks kosong, tukar namanya kepada gambar.jpg, kemudian muat naik. Ia mesti ditolak, dan mesejnya menyebut fail itu bukan gambar yang sah.
  • Muat naik gambar yang lebih besar daripada had saiz. Ia mesti ditolak walaupun ia gambar yang sah.
  • Tukar tarikh satu baris dalam jadual kepada 45 minit lalu, kemudian buka halaman. Baris itu dan failnya patut hilang dengan sendirinya.

Apa yang patut ditambah kemudian

  • Jana gambar kecil untuk senarai, supaya halaman tidak memuatkan gambar penuh.
  • Simpan gambar di luar folder laman web, kemudian hidangkannya melalui satu halaman CFML yang memeriksa kebenaran.
  • Hadkan bilangan gambar bagi setiap pembaca, bukan hanya bagi setiap alamat IP.
  • Catat setiap muat naik ke dalam log, supaya masalah boleh disiasat kemudian.

Cuba dan muat turun

Contoh ini boleh dicuba terus, dan kod penuhnya boleh dimuat turun bersama skrip jadual dan arahan pemasangan dalam bahasa Melayu. Dua tutorial lain dalam siri yang sama membincangkan CRUD dengan teg asas, dan borang log masuk yang selamat.

Baca juga di laman ini

Sumber yang disemak

Maklumat dalam tulisan ini disemak dengan sumber di bawah. Bila keadaan berubah (harga, waktu, terma), sumber inilah yang paling tepat — bukan halaman ini.

Dapat tulisan baharu terus ke e-mel

Sekali sekala sahaja: panduan web, berita AI, dan tempat menarik di Kelantan. Tiada iklan, dan e-mel encik tidak dikongsi dengan sesiapa.

Berhenti langgan bila-bila masa, satu klik.

Kongsi WhatsApp Facebook

Berkaitan halaman ini

Pautan afiliasi Shopee — saya mungkin menerima komisen, harga awak tetap sama.

Senarai penuh ada di kedai afiliasi.

Rujukan yang mungkin berguna

Pautan rujukan — anda dapat ganjaran pendaftaran, saya juga dapat ganjaran. Tiada kos tambahan untuk anda.

Bank

Ryt Bank — Bank digital berlesen di Malaysia

Ryt Bank ialah bank digital berlesen di Malaysia, disokong YTL Digital Capital dan Sea Limited (kumpulan di sebalik Shopee). Semua urusan melalui aplikasi — buka akaun, simpanan dan pembayaran tanpa cawangan.

Ganjaran: RM5 dijamin selepas mendaftar; sehingga RM100 jika anda mencuba Ryt AI atau Ryt Groups (kempen ulang tahun pertama Ryt Bank — tertakluk syarat)

Kod: EL5QB

Daftar di Ryt Bank

Minyak

Setel — Isi minyak di Petronas, dapat RM3

Setel ialah aplikasi pembayaran minyak di stesen Petronas — bayar terus dari telefon. Dengan kod rujukan di bawah, anda dan saya masing-masing menerima RM3 selepas anda belanja RM30 untuk minyak atau di Kedai Mesra.

Ganjaran: RM3 untuk kedua-dua pihak selepas belanja RM30 (tertakluk syarat Setel)

Kod: ffgaa

Daftar di Setel

Senarai penuh (bank digital, minyak, penghantaran) ada di halaman rujukan. Maklumat di atas ialah ringkasan terma penyedia — sila semak terma penuh di laman rasmi mereka.