Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

php cara menautkan file dari server file ke info itu dari database

Saya pikir saya akan menulis singkat (bagi saya ini singkat) "jawaban" supaya saya bisa meringkas poin saya.

Beberapa "Praktik Terbaik" saat membuat sistem penyimpanan file. Penyimpanan file adalah kategori yang luas sehingga jarak tempuh Anda mungkin berbeda untuk beberapa di antaranya. Anggap saja sebagai saran tentang apa yang menurut saya berfungsi dengan baik.

Nama file Jangan menyimpan file dengan nama yang diberikan oleh pengguna akhir. Mereka dapat dan akan menggunakan semua jenis karakter jelek yang akan membuat hidup Anda sengsara. Beberapa bisa seburuk ' tanda kutip tunggal, yang di linux pada dasarnya membuatnya jadi tidak mungkin untuk membaca, atau bahkan menghapus file ( langsung ). Beberapa hal bisa tampak sederhana seperti spasi tetapi tergantung di mana Anda menggunakannya dan OS di server Anda, Anda dapat berakhir dengan one%20two.txt atau one+two.txt atau one two.txt yang mungkin atau mungkin tidak menimbulkan semua jenis masalah di tautan Anda.

Hal terbaik yang harus dilakukan adalah membuat hash, seperti sha1 ini bisa sesederhana {user_id}{orgianl_name} Nama pengguna membuatnya lebih kecil kemungkinannya untuk bertabrakan dengan nama file pengguna lain.

Saya lebih suka melakukan file_hash('sha1', $contents) dengan begitu jika seseorang mengunggah file yang sama lebih dari sekali, Anda dapat menangkapnya (isinya sama hashnya sama). Tetapi jika Anda berharap memiliki file besar, Anda mungkin ingin melakukan penandaan bangku untuk melihat jenis kinerja yang dimilikinya. Saya kebanyakan menangani file kecil sehingga berfungsi dengan baik untuk itu.-perhatikan- bahwa dengan stempel waktu file masih dapat disimpan karena nama lengkapnya berbeda, tetapi membuatnya cukup mudah dilihat, dan dapat diverifikasi di database.

Terlepas dari apa yang Anda lakukan, saya akan mengawalinya dengan stempel waktu time().'-'.$filename . Ini adalah informasi yang berguna untuk dimiliki, karena ini adalah waktu mutlak file itu dibuat.

Adapun nama pengguna memberikan file. Simpan saja dalam catatan database. Dengan cara ini Anda dapat menunjukkan kepada mereka nama yang mereka harapkan, tetapi gunakan nama yang Anda tahu selalu aman untuk tautan.

$filename ='beberapa jelek^ fileane.jpg';

$ext = strrchr($filename, '.');

echo "\nExt: {$ext}\n";

$hash = sha1('some crapy^ fileane.jpg');

echo "Hash: {$hash}\n";

$time = time();

echo "Timestamp: {$time}\n";

$hashname = $time.'-'.$hash.$ext;

echo "Hashname: $hashname\n";

Keluaran

Ext: .jpg
Hash: bb9d2c2c7c73bb8248537a701870e35742b41c02
Timestamp: 1511853063
Hashname: 1511853063-bb9d2c2c7c73bb8248537a701870e35742b41c02.jpg

Anda dapat mencobanya di sini

Jalur jangan pernah menyimpan path lengkap ke file. Yang Anda butuhkan dalam database adalah hash dari pembuatan nama hash. Jalur "root" ke folder tempat file disimpan harus dilakukan dalam PHP. Ini memiliki beberapa manfaat.

  • mencegah pemindahan direktori. Karena Anda tidak melewati bagian jalan mana pun di sekitar Anda, Anda tidak perlu terlalu khawatir tentang seseorang yang tergelincir \..\.. di sana dan pergi ke tempat-tempat yang tidak seharusnya. Contoh buruknya adalah seseorang menimpa .htpassword file dengan mengunggah file bernama itu dengan direktori melintang di dalamnya.
  • Memiliki tautan yang tampak lebih seragam, ukuran seragam, kumpulan karakter yang seragam.

https://en.wikipedia.org/wiki/Directory_traversal_attack

  • Pemeliharaan. Jalur berubah, Server berubah. Tuntutan pada sistem Anda berubah. Jika Anda perlu memindahkan file-file itu, tetapi Anda menyimpan path lengkap absolut ke mereka di DB, Anda terjebak menempelkan semuanya bersama-sama dengan symlinks atau memperbarui semua catatan Anda.

Ada beberapa pengecualian untuk ini. Jika Anda ingin menyimpannya di folder bulanan atau berdasarkan nama pengguna. Anda dapat menyimpan bagian jalur itu, di bidang terpisah. Tetapi bahkan dalam kasus itu, Anda dapat membangunnya secara dinamis berdasarkan data yang disimpan dalam catatan. Saya telah menemukan yang terbaik untuk menyimpan info jalur sesedikit mungkin. Dan mereka membuat konfigurasi atau konstanta yang dapat Anda gunakan di semua tempat yang Anda perlukan untuk meletakkan jalur ke file.

Juga path dan link sangat berbeda, jadi dengan menyimpan hanya nama Anda dapat menautkannya dari halaman PHP apa pun yang Anda inginkan tanpa harus mengurangi data dari jalurnya. Saya selalu merasa lebih mudah untuk menambahkan nama file daripada mengurangi dari jalur.

Basis Data (hanya beberapa saran, penggunaan dapat bervariasi )Seperti biasa dengan data tanyakan pada diri sendiri, siapa, apa, di mana, kapan

  • id - int peningkatan otomatis kunci utama
  • id_pengguna - int kunci asing, siapa mengunggahnya
  • hash - char[40] *sha1*, unique apa hashnya
  • nama hash - varchar {timestampl}-{hash}.{ext} di mana nama file di hard drive
  • nama file - varchar nama asli yang diberikan oleh pengguna, dengan begitu kita dapat menunjukkan kepada mereka nama yang mereka harapkan ( jika itu penting )
  • status - enum[public,private,deleted,pending.. etc] status file, tergantung pada kasus penggunaan Anda, Anda mungkin harus meninjau file, atau mungkin sebagian bersifat pribadi hanya pengguna yang dapat melihatnya, mungkin sebagian bersifat publik, dll.
  • status_date - timestamp|datetime kali statusnya berubah.
  • tanggal_buat - timestamp|datetime kapan saat file dibuat, stempel waktu lebih disukai karena membuat beberapa hal lebih mudah tetapi harus menggunakan stempel waktu yang sama dalam nama hash, dalam hal ini.
  • ketik - varchar - mime type, bisa berguna untuk setting mime type saat download dll.

Jika Anda mengharapkan pengguna yang berbeda untuk mengunggah file yang sama dan Anda menggunakan file_hash anda dapat membuat hash bidang indeks unik gabungan dari user_id dan hash cara ini hanya akan bentrok jika pengguna yang sama mengunggah file yang sama. Anda juga dapat melakukannya berdasarkan stempel waktu dan hash, tergantung pada kebutuhan Anda.

Itu hal dasar yang bisa saya pikirkan, ini tidak mutlak hanya beberapa bidang yang saya pikir akan berguna.

Sangat berguna untuk memiliki hash sendiri, jika Anda menyimpannya sendiri, Anda dapat menyimpannya di CHAR(40) untuk sha1 (memakan lebih sedikit ruang di DB daripada VARCHAR ) dan atur susunannya, ke UTF8_bin yang biner. Hal ini membuat pencarian di atasnya peka huruf besar/kecil. Meskipun kemungkinan tabrakan hash kecil, ini hanya menambahkan sedikit perlindungan karena hash adalah huruf besar dan kecil.

Anda selalu dapat membuat hashname dengan cepat jika Anda menyimpan ekstensi, dan stempel waktu terpisah. Jika Anda mendapati diri Anda membuat sesuatu berulang kali, Anda mungkin hanya ingin menyimpannya di DB untuk menyederhanakan pekerjaan di PHP.

Saya suka hanya menempatkan hash di tautan, tidak ada ekstensi apa pun sehingga tautan saya terlihat seperti ini.

http://www.example.com/download/ad87109bfff0765f4dd8cf4943b04d16a4070fea

Sangat sederhana, generik nyata, aman di url selalu ukuran yang sama dll.

hashname untuk "file" ini akan menjadi seperti ini

1511848005-ad87109bfff0765f4dd8cf4943b04d16a4070fea.jpg

Jika Anda memiliki konflik dengan file yang sama dan pengguna yang berbeda (yang saya sebutkan di atas). Anda selalu dapat menambahkan bagian stempel waktu ke dalam tautan, user_id atau keduanya. Jika Anda menggunakan user_id, mungkin berguna untuk meninggalkannya dengan nol. Misalnya beberapa pengguna mungkin memiliki ID:1 dan beberapa mungkin ID:234 jadi Anda bisa meninggalkannya di 4 tempat dan menjadikannya 0001 dan 0234 . Kemudian tambahkan itu ke hash, yang hampir tidak terlihat:

1511848005-ad87109bfff0765f4dd8cf4943b04d16a4070fea0234.jpg

Yang penting di sini adalah karena sha1 selalu 40 dan id selalu 4 kita dapat memisahkan keduanya secara akurat dan mudah. Dan dengan cara ini, Anda masih bisa mencarinya secara unik. Ada banyak pilihan yang berbeda tetapi banyak tergantung pada kebutuhan Anda.

Akses Seperti mengunduh. Anda harus selalu menampilkan file dengan PHP, jangan beri mereka akses langsung ke file. Cara terbaik adalah menyimpan file di luar webroot ( di atas public_html , atau www folder). Kemudian di PHP Anda dapat mengatur header ke jenis yang benar dan pada dasarnya membaca file. Ini berfungsi untuk hampir semua hal kecuali video. Saya tidak menangani video jadi itu topik di luar pengalaman saya. Tapi menurut saya lebih baik untuk memikirkannya karena semua data file adalah teks, header-nya yang membuat teks itu menjadi gambar, atau file excel atau pdf.

Keuntungan besar dari tidak memberi mereka akses langsung ke file adalah jika Anda memiliki situs keanggotaan, tidak ingin konten Anda dapat diakses tanpa login, Anda dapat dengan mudah memeriksa PHP jika mereka login sebelum memberi mereka konten. Dan, karena file berada di luar webroot, mereka tidak dapat mengaksesnya dengan cara lain.

Yang paling penting adalah memilih sesuatu yang konsisten, yang masih cukup fleksibel untuk menangani semua kebutuhan Anda.

Saya yakin saya dapat membuat lebih banyak lagi, tetapi jika Anda memiliki saran, jangan ragu untuk berkomentar.

ALUR PROSES DASAR

  1. Pengguna mengirimkan formulir (enctype="multipart/form-data" )

https://www.w3schools.com/tags/att_form_enctype.asp

  1. Server menerima kiriman dari formulir, Super Globals $_POST dan $_FILES

http://php.net/manual/en/reserved.variables.files .php

$_FILES = [
 'fieldname' => [
        'name' => "MyFile.txt" // (comes from the browser, so treat as tainted)
        'type' => "text/plain" //  (not sure where it gets this from - assume the browser, so treat as tainted)
        'tmp_name' => "/tmp/php/php1h4j1o" // (could be anywhere on your system, depending on your config settings, but the user has no control, so this isn't tainted)
        'error' => "0" //UPLOAD_ERR_OK  (= 0)
        'size' => "123" //   (the size in bytes)
    ]
 ];
  1. Periksa kesalahan if(!$_FILES['fielname']['error'])

  2. Bersihkan nama tampilan $filename = htmlentities($str, ENT_NOQUOTES, "UTF-8");

  3. Simpan file, buat catatan DB ( PSUDO-CODE )

Seperti ini:

 $path = __DIR__.'/uploads/'; //for exmaple

$time = time();
$hash = hash_file('sha1',$_FILES['fielname']['tmp_name']);
$type = $_FILES['fielname']['type'];
$hashname = $time.'-'.$hash.strrchr($_FILES['fielname']['name'], '.');
$status = 'pending';

if(!move_uploaded_file ($_FILES['fielname']['tmp_name'], $path.$hashname  )){
     //failed
     //do somehing for errors.
     die();
}


//store record in db

http://php.net/manual/en/function.move -upload-file.php

  1. Buat tautan (bervariasi berdasarkan perutean), cara sederhana adalah dengan membuat tautan Anda seperti ini http://www.example.com/download?file={$hash} tapi lebih jelek dari http://www.example.com/download/{$hash}

  2. tautan klik pengguna menuju ke halaman unduhan.

dapatkan INPUT dan cari catatan

$hash = $_GET['file'];

$stmt = $PDO->prepare("SELECT * FROM attachments WHERE hash = :hash LIMIT 1");  
$stmt->execute([":hash" => $hash]);

$row = $stmt->fetch(PDO::FETCH_ASSOC);

print_r($row);

http://php.net/manual/en/intro.pdo.php

dll....

Semangat!




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysql:sangat sederhana SELECT id ORDER BY LIMIT tidak akan menggunakan INDEX seperti yang diharapkan (?!)

  2. kueri mysql TAMPILKAN KOLOM DARI tabel seperti 'colmunname':pertanyaan

  3. Ganti nama tabel Mysql dengan concat

  4. kesalahan pembatas mysql

  5. php/mysql tambahkan baris bersama untuk mendapatkan total