2012-12-20 35 views
4

在Web開發人員的生活中,稍晚或更早,您必須處理用戶上傳的文件和圖像。上傳,處理,存儲和交付用戶提供的文件和圖像

常見問題:

如何上傳?

現代瀏覽器和技術允許多種方式的用戶提供的文件上傳到我的服務器。什麼是最佳實踐,我需要考慮什麼?

我該如何處理?

一旦上傳完成後,我需要了解哪些有關安全和

如何存儲和傳輸文件的進一步處理?

是關於如何存儲上傳的文件有最佳做法?

免責聲明:我已經把近30分鐘進入下面的答案,最初的問題輾轉所以我決定要求與用戶提供的文件打交道時,用戶可能面臨的一般性問題。見我的答案,你可以自由地作出貢獻,並添加自己的想法和經驗

+0

對於在發佈答案之前已刪除的問題,這是一個艱難的工作答案:) –

+0

+1爲您的努力...但嘗試提出像哈克拉這樣的問題編輯,無論它的教程..而不是免責聲明..我們都知道噸它需要付出努力和無價的時間用良好的內容來寫這麼多.... –

回答

21

有各種各樣的技術和圖書館這當中沒有「最好」的方式爲每個這樣的步驟,但一大堆的建立方法和最佳實踐可以幫助您實現用戶友好的上傳,安全性和速度。

對於另一個不幸被刪除的問題,我寫了這個小指南。

用戶提供的文件或圖像走過幾個階段,在它的壽命:

  1. 上傳本身
  2. validaton
  3. 處理存儲(例如類型轉換,縮放,縮略圖生成,.. 。)
  4. 存儲關於前端側
  5. 輸送

這將ADRESS的所有步驟,並提供了示例儘可能

1.上傳

現代Web瀏覽器都提供了幾種方法來上傳文件。

最簡單的方法是創建一個簡單的<input type="file" name="userFile" />標籤的形式。一旦提交表格,文件將使用POST發送,並可通過$_FILESsuperglobal在PHP

訪問1.1。在HTML

<form action="upload.php" method="post" enctype="multipart/form-data"> 
    <input type="file" name="userFile1" /> 
    <input type="file" name="userFile2" /> 
    <input type="submit" value="upload files" /> 
</form> 

當表單提交簡單的形式,一個POST請求被髮送到上傳。PHP 這種上傳的不是很用戶友好。您的用戶將無法看到上傳任何進展,並上傳多個文件將是一個痛苦

1.2。 JavaScript的AJAX上傳

在這種解決方案中,POST與JavaScript

http://www.saaraan.com/2012/05/ajax-image-upload-with-progressbar-with-jquery-and-php

1.3異步完成。 HTML 5上傳

現代的瀏覽器支持HTML5,它允許非常好的,用戶友好上傳口罩進度條和預覽 - 邊境自己的創造力

例如,我真的很喜歡這個演示:http://html5demos.com/dnd-upload

在服務器端

無論您決定使用哪種上傳技術,上傳將以發送到腳本的HTTP POST結束。所有進一步的處理將在服務器上完成。

PHP複製文件到臨時路徑(upload_tmp_dir

還有一些其他的上傳相關的設置,你可以在你的php.ini或調整與ini_set上即時:http://php.net/manual/en/ini.core.php#ini.sect.file-uploads

upload.php

<pre> 
<?php 
print_r($_FILES); 

這就是$_FILES超全球在成功上傳後的樣子。

  • 名稱:原來的名字
  • 類型:瀏覽器提供的mime-type
  • 大小:字節大小
  • tmp_name的值:臨時文件名的服務器上
  • 錯誤:錯誤代碼爲described here,0時,一切都變得文件

每個文件都有它自己的指標

Array 
( 
    [userFile1] => Array 
    (
     [name] => i_love_ponies.png 
     [type] => image/png 
     [size] => 42233 
     [tmp_name] => /tmp/_x123tfsdayx134 
     [error] => 0 
    ) 
    [userFile2] => Array 
    (
     [name] => ponies_run_my_server.png 
     [type] => image/png 
     [size] => 12325 
     [tmp_name] => /tmp/_x3123asdad3ssy 
     [error] => 0 
    ) 
) 

一些提示

如果你期待大文件,考慮Web服務器和PHP執行超時。如果上傳需要10分鐘,則不希望用戶最終遇到錯誤。

在PHP中,你可以增加max_execution_time

2。驗證

問題,你可能要問

難道我想只允許特定的文件 - 我收到什麼樣的文件?

您在$_FILES數組中找到的類型由瀏覽器設置。如果您想確定上傳的是哪種類型,則可以使用PHP的fileinfo extension

這個例子會檢查上傳自己的成功和寫入允許的類型的文件合併成一個新的數組furter處理

$allowedTypes = array(
    'image/png' 
    'image/gif' 
    'image/jpeg' 
); 

$useFiles = array(); 

$finfo = new finfo(FILEINFO_MIME_TYPE); 
foreach ($_FILES as $index => $file) 
{ 
    if ($file['error'] === UPLOAD_ERR_OK) { 
     $type = $finfo->file($file['tmp_name']); 
     if (in_array($type, $allowedTypes)) { 
      $useFiles[$index] = $file; 
     } 
    } 
} 

難道我要設置最大文件大小 - 什麼是大小?

在這種情況下,您可以安全地依賴$_FILES['key']['size']值,即以字節爲單位的大小。你不應該僅僅依靠客戶端設置文件大小限制

如果談論圖像,我想縮放或創建縮略圖 - 圖像尺寸是什麼?

看一看getimagesize確定圖像尺寸

3.加工

文件保存到它,你可能想要做一些處理與它的最終位置之前。 這就是你可以

公共庫是gd libimagick。我個人更喜歡gd lib。這是一個更手動的工作,但速度更快,默認情況下大多數情況下都是安裝的,或者安裝起來很簡單。 ImageMagick的本身有一個非常龐大的圖像處理功能池

4.將數據存儲

現在是時候談論存儲。首先是將臨時文件複製到臨時或最終位置的保存方式。

您應該使用move_uploaded_file

move_uploaded_file($useFiles['tmp_name'], $destination); 

再次,沒有「最好的方法」,用於存儲,這取決於你的環境,文件和使用。我會談幾個

4.1。服務器文件系統

這可能是存儲文件的最常用和最簡單的方法。您可以簡單地使用已經運行的Web服務器靜態地提供文件。這通常是您的文檔根目錄中的一個位置。

爲了讓您的生活更輕鬆,您可以將文件名保存到數據庫中 - 最好參考或引用像用戶或位置這樣的連接數據。

出於各種原因,您不應將所有文件保存到同一文件夾中。

您必須爲每個文件生成一個唯一的名稱,否則使用新文件覆蓋現有的文件。另外,通常的文件系統越來越慢地尋找節點中越來越多的文件。當文件被請求傳送時,這會導致響應時間變慢。

你可以將其保存到一個文件夾爲每個用戶

/uploaded/user-id/file.jpg 

如果你期望很多每個用戶,你可能分裂FILNAME的校驗文件,深入瞭解文件夾結構

例如

$path = $_SERVER['DOCUMENT_ROOT'] . '/uploaded/' . $userId . '/' . chunk_split(md5($useFiles['index']['name']), 12, '/'); 

會導致

/var/www/htdocs/uploaded/1/97e262286853/d52aa8c58eb7/f0431f03/ 

4.2。數據庫

您可以使用blob類型將文件存儲到MySQL數據庫中。我不推薦這一般

4.3。內容分發網絡

如果您預計大量的流量在全球各地,你可能要考慮在CDN存儲你的文件,如Amazon S3用的Cloudfront。

S3是文件備份到5TB的廉價,可靠的存儲(據我所知)

http://www.9lessons.info/2012/08/upload-files-to-amazon-s3-php.html

你將不必擔心文件備份,可用硬盤尺寸,交貨速度等。等Cloudfront在S3的頂部添加了CDN圖層,並在世界各地的邊緣位置