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.
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
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>
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.
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.
Halaman ini dicetak tanpa menu, borang langgan dan jalur sisi.
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.