[WWW] 超犯規的檔案上傳工具 Plupload

官方網站:http://www.plupload.com/

噗浪討論:http://www.plurk.com/p/44o98a

更新,讓他自己取附檔名:

修改 plupload.js 檔案,第 717 行的 bind 那一段,如下:

/// 原本是這行
file.target_name = file.id + '.tmp';

/// 改成這樣
var parts = /^(.+)(\.[^.]+)$/.exec(file.name);
if (parts) {
  name = parts[1];
  ext = parts[2];
  file.target_name = file.id + ext;
} else {
  file.target_name = file.id + '.tmp';
}

改完之後要把 full.min 重新 build 一次,還有 plupload.min.js 也要重新包過。

為什麼說他犯規,是因為他不只是單純的 swfuploader,還支援了 HTML4 Form, HTML5, Gears, Silverlight 跟 Yahoo! 自家的 BrowserPlus。讓我想起之前為了做多檔上傳,還自己硬刻 Flex 來用的杯具!使用的方法很簡單,到官方下載檔案解壓縮後,照著 example 就可以用。這不是犯規是甚麼,你說說看,你說說看啊(摔滑鼠)。

官方預設的伺服端語言是 PHP,不過我想改用 ASP 也不是不可以,只要依照他的規定傳回 JSON-RPC 就可以了。所以,我們來看看他傳了甚麼東西(使用每一種 runtime 傳的東西大同小異,不過還是有點區別)。

以下都是以 Firefox 3.6, Firebug 1.5.2 觀察之:

  • 以 Flash 模式上傳:

    POST /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp&chunk=0&chunks=4

    POST
    /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp&chunk=1&chunks=4


    POST
    /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp&chunk=2&chunks=4


    POST
    /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp&chunk=3&chunks=4

  • 以 Gears 模式上傳:

    在 Firefox 3.6 我有錯誤訊息,但是在 Chrome 中則正常,不知道有沒有人可以試試看?

    [Exception... "Component returned failure code: 0x80004001 (NS_ERROR_NOT_IMPLEMENTED) [nsILoadGroup.groupObserver]"
    nsresult: "0x80004001 (NS_ERROR_NOT_IMPLEMENTED)"
    location: "JS frame :: file:///...(FireFox 擴充元件資料夾).../componentCollectorService.js :: anonymous :: line 1238" data: no]
    file:///...(FireFox 擴充元件資料夾).../componentCollectorService.js
    Line 1238

  • 以 Silverlight 模式上傳:

    POST
    /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp&chunk=0&chunks=1

  • 以 HTML 5 模式上傳:

    POST /upload.php?name=p14t7vnrtf9din2dj84j3i12r96.tmp

  • 以 BrowserPlus 模式上傳:

    完全抓不到任何傳輸動作。

  • 以 HTML4 Form 模式上傳:

    POST /upload.php?name=3848135463_8f288fd728_o.jpg

接著,我們來看伺服器端收到了甚麼(以下以 PHP 為例,將 POST, FILES, GET 給 dump 出來):

  • 以 Flash 模式上傳:

    POST 與 FILES 皆為空值,chunks 為 4

  • 以 Gears 模式上傳:

    POST 與 FILES 皆為空值,chunks 為 3

  • 以 Silverlight 模式上傳:

    POST 與 FILES 皆為空值,chunks 為 3

  • 以 HTML 5 模式上傳:

    POST 與 FILES 皆為空值,無 chunks 值

  • 以 BrowserPlus 模式上傳:

    POST 為空值,chunks 為 1,FILES 為 PHP 預設數值格式。

  • 以 HTML4 Form 模式上傳:

    三項皆有值,無 chunks 值,POST 為:

    array(15) {
      ["flash_uploader_count"]=>
      string(1) "0"
      ["gears_uploader_0_tmpname"]=>
      string(32) "p14t82ul97ra9bfricr1qgq1jhe6.tmp"
      ["gears_uploader_0_name"]=>
      string(27) "3848135463_8f288fd728_o.jpg"
      ["gears_uploader_0_status"]=>
      string(4) "done"
      ["gears_uploader_count"]=>
      string(1) "1"
      ["silverlight_uploader_count"]=>
      string(1) "0"
      ["html5_uploader_0_tmpname"]=>
      string(33) "p14t830nu8b71h0v1g5d1pj41n7ga.tmp"
      ["html5_uploader_0_name"]=>
      string(50) "22537_329169913921_674443921_3751384_8120847_n.jpg"
      ["html5_uploader_0_status"]=>
      string(4) "done"
      ["html5_uploader_count"]=>
      string(1) "1"
      ["browserplus_uploader_0_tmpname"]=>
      string(33) "p14t8320qg83bhq71rt114d81h8mb.tmp"
      ["browserplus_uploader_0_name"]=>
      string(8) "6847.jpg"
      ["browserplus_uploader_0_status"]=>
      string(4) "done"
      ["browserplus_uploader_count"]=>
      string(1) "1"
      ["html4_uploader_count"]=>
      string(1) "0"
    }

要打開 $_FILES 這個值,需要在設定內加入 mutlipart = true

這樣的話,在你的傳值的部份就會傳入 $_FILES 的陣列,對於有需要的人也是不錯的應用。至於他是否因為打開之後就關閉 chunks 上傳模式,這一點未知,但是我想應該不是(單純個人猜測)吧。

要額外傳送 $_POST,需要在設定加入 multipart_params: { 'name1' : 'value1', 'name2' : 'value2' ... } 依此類推。

當你開啟 multipart 時,在官方的範例 upload.php 中有一段是檢查 HTTP_CONTENT_TYPE,這個部份在我的主機上,其檢查的是 $_SERVER["CONTENT_TYPE"],並非範例中所述是 $_SERVER["HTTP_CONTENT_TYPE"] 關於這一點要請大家自行去檢查。

另外,他上傳之後,是使用 guid() 來取名字,附檔名也一律使用 .tmp(不知道為什麼,這樣很不方便),所以如果你上傳的是圖片的話,你必須要把附檔名給改回來,他好像不會幫你做這件事情。而令人納悶的是,他預設使用 chunk 上傳,但是卻不幫你把檔案名稱(特別是附檔名)改回正確的 MIME-Type,這一點很奇怪。

所以,用 chunk 上傳的美意,毀在檔案名稱不正確的狀況下,似乎有點詭譎。

基本上,除了在 Webkit 底下使用 HTML5 的模式,會無法開啟 multipart 之外,其他都還算蠻順暢的,至於官方提供的關於 multipart 的部份,建議還是自己改寫比較好一點(誠心建議)。

那個 chunking 不幫我改附檔名真的讓我揪賭爛!

Hina Chen
偏執與強迫症的患者,算不上是無可救藥,只是我已經遇上我的良醫了。
Taipei