2015-04-08 39 views
3

我試圖在jquery的$ .ajax請求時發送php服務器生成的zip文件。

這是我的代碼:

PHP:

 $file = tempnam($a_folder_path, "zip"); 

     $zip = new ZipArchive(); 
     $zip->open($file, ZipArchive::OVERWRITE); 
     $zip->addFile($path_to_json, 'data.json'); 
     $zip->close(); 

     rename($file, $file . '.zip'); 

     $filename = basename($file . '.zip'); 
     $filepath = $file . '.zip'; 
     while (ob_get_level()) { 
      ob_end_clean(); 
     } 
     header("Pragma: public"); 
     header("Expires: 0"); 
     header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0"); 
     header("Content-Description: File Transfer"); 
     header("Content-type: application/octet-stream"); 
     header("Content-Disposition: attachment; filename=\"".$filename."\""); 
     header("Content-Transfer-Encoding: binary"); 
     header("Content-Length: ".filesize($filepath)); 
     ob_end_flush(); 
     echo file_get_contents($filepath); 
     //@readfile($filepath); 

的javascript:

$.ajax(
     { 
      url: myUrl,     
      type: 'POST',     
      data: { 
       "leData"  : "some_data" 
      }, 
      context: document.body, 
      cache: false, 
      success: function(data) { 
       console.log(data); 
       console.log(data.length); 
       var bytes = new Uint8Array(data.length); 
       for (var i=0; i<data.length; i++) { 
        bytes[i] = data.charCodeAt(i); 
       } 
       blob = new Blob([bytes], {type: "application/zip"}) 
       saveAs(blob, "test.zip");//trying to access data with FileSave.js 
       zip.load(data);//trying to access data with JSZip.js 
       jsonData = JSON.parse(zip.file('shouldBeThere.json').asText()); 
      }, 
      error: function() { 
       alert('error'); 
      } 
     } 
    ); 

會發生什麼:

  1. 服務器創建的zip文件,我問它,並且這個文件沒有損壞。其中包含shouldBeThere.json。
  2. 服務器將數據發送到前端。
  3. console.log(data);在JavaScript中打印一個字符串與我通過使用文本編輯器打開在服務器上創建的zip文件所得到的幾乎相同。
  4. console.log(data.length);根據chrome的devtools,在javascript中輸入的行數小於響應頭的內容長度。也許提示數據損壞。
  5. saveAs使用正確的名稱創建一個包含文件的zip文件,但是當我嘗試解壓縮文件時,7zip顯示錯誤:「嘗試在文件開始之前移動文件指針」。 6.JSZip似乎加載數據,但然後zip.file('shouldBeThere.json')爲空。

問題是我不知道如果問題來自PHP或從JavaScript。我不知道如果PHP發送損壞的zip或如果JavaScript不正確讀取它。

我已經嘗試了所有在互聯網上找到的php頭組合和方法。我也嘗試在javascript中做不同的事情:使用ArrayBuffer而不是Uint8Array,在Blob()中使用{type:「application/octet-stream」}將字節而不是數據傳遞給zip.load()。

+2

AJAX是不適合這個。你可以使用'窗口。打開(url);'URL是鏈接到你的php文件的地方。由於它下載一個文件,窗口將會彈出一秒鐘。 – Slim

+0

類似的問題已經在這裏找到答案: http://stackoverflow.com/questions/23676748/download-zip-file-with-jquery-from-ajax-post-request – Erick

+0

首先,檢查問題來自PHP。 轉到您可以下載zip文件的URL(直接下載)並檢查是否可以解壓文件。 如果是的話,問題來自JS。 查看你的代碼後,你不會設置ajax「響應類型」,默認是「text/html」...對於一個大文件,這不是文本而是二進制,你可以使用「Blob」或「arraybuffer」但我不確定,你必須創建一個JSFiddle – Jordan

回答

5

我終於找到了一個解決方案:它必須指定給ajax接收的數據類型,然後將這個unicode數據轉換爲字符。這裏是我的新JavaScript代碼:

$.ajax(
    { 
     url: myUrl,     
     type: 'POST',     
     data: { 
      "leData"  : "some_data" 
     }, 
     context: document.body, 
     cache: false, 
     dataType: 'text',         //solution code 
     mimeType: 'text/plain; charset=x-user-defined',  //solution code 
     success: function(data) { 
      console.log(data); 
      console.log(data.length); 
      newContent = "";        //solution code 
      for (var i = 0; i < data.length; i++) {   //solution code 
       newContent += String.fromCharCode(data.charCodeAt(i) & 0xFF); //solution code 
      } 
      var bytes = new Uint8Array(newContent.length);      //modified 
      for (var i=0; i<newContent.length; i++) {       //modified 
       bytes[i] = newContent.charCodeAt(i);       //modified 
      } 
      blob = new Blob([bytes], {type: "application/zip"}) 
      saveAs(blob, "test.zip"); 
      zip.load(newContent);            //modified 
      jsonData = JSON.parse(zip.file('shouldBeThere.json').asText()); 
     }, 
     error: function() { 
      alert('error'); 
     } 
    } 
); 

我的php代碼很好,它甚至沒有標題。這裏是最小的PHP代碼,我需要: 「發送PHP的URL的請求創建一個目錄的zip和:

$file = tempnam($a_folder_path, "zip"); 

    $zip = new ZipArchive(); 
    $zip->open($file, ZipArchive::OVERWRITE); 
    $zip->addFile($path_to_json, 'data.json'); 
    $zip->close(); 

    rename($file, $file . '.zip'); 

    echo file_get_contents($file . '.zip'); 

解決方案通過this

+0

'xhr.responseType =「arraybuffer」;'會是最好的,但jQuery不支持它(請參閱https://github.com/jquery/jquery/pull/1525)。 https://github.com/acigna/jquery-ajax-native可以解決這個問題。 –

+0

「mimeType:'text/plain; charset = x-user-defined'」保存我的一天! – MeGoodGuy

0

我正在尋找對以下問題的解決方案的啓發通過使用ajax響應下載它。「

下面的代碼工作:對於ZIP

PHP部分:

// Function for creating a zip of a directory 
function zipFilesAndDownload($directory, $file_names) { 
$zip = new ZipArchive(); 

if ($zip->open("../temp/$directory.zip", ZIPARCHIVE::CREATE) !== TRUE) { 
    exit("Error on creating '../temp/$directory.zip'"); 
} 

foreach ($file_names as $file) { 
    $zip->addFile($file, substr($file, strrpos($file, "/") + 1)); 
} 
$zip->close(); 
readfile("../temp/$directory.zip"); 
unlink("../temp/$directory.zip"); 
} 

// Code for creating array of filenames 
$directory = $_POST['directory']; // e.g. a directory with ID "123" 
$dirToZip = "../uploaddir/$directory"; 
if ($handle = opendir($dirToZip)) { 
    $file_names = array(); 
    while (($file = readdir($handle)) !== false) { 
     if ($file != "." && $file != "..") { 
      array_push($file_names, "$dirToZip/$file"); 
     } 
    } 
    closedir($handle); 
    zipFilesAndDownload($directory, $file_names); 
} 

JS部分:

$(document).on('click', '#downloadDirectory', function() { 

     var directory = '123'; 
     $.ajax({ 
     type: 'POST', 
     url: '../createZip.php', 
     data: {"directory": directory}, 
     dataType: 'text', 
     mimeType: 'text/plain; charset=x-user-defined', 
     success: function (data) { 
       var bytes = new Uint8Array(data.length); 
       for (var i = 0; i < data.length; i++) { 
        bytes[i] = data.charCodeAt(i); 
       } 
       blob = new Blob([bytes], {type: "application/zip"}) 
        saveAs(blob, "pictures.zip"); // "saveAs" function is provided in FileSaver.js 
       } 
     }); 
});