2015-04-08 42 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 
       } 
     }); 
});