二进制XHR结果到文件blob - Jquery

时间:2015-10-26 10:23:01

标签: javascript jquery web-services pdf download

下载文档的Web服务返回以下内容:

%PDF-1.5
%����
1 0 obj
<</Type/Catalog/Pages 2 0 R/Lang(en-GB) /StructTreeRoot 14 0 R/MarkInfo<</Marked true>>>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[ 3 0 R] >>
endobj
3 0 obj
<</Type/Page/Parent 2 0 R/Resources<</Font<</F1 5 0 R/F2 8 0 R>>/ExtGState<</GS7 7 0 R>>/ProcSet[/PDF
/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 4 0 R/Group<</Type/Group/S/Transparency
/CS/DeviceRGB>>/Tabs/S/StructParents 0>>
endobj
4 0 obj

要将此数据转换为文件,请使用以下代码:

$.ajax({
      url: "/documents/docDownload",
      type: "GET",
      async:   true,
      headers: {
        responseType: "arraybuffer"
      },
      success: function(data,status,xhr) {
        var file = new Blob([data], {type: 'application/pdf'});
        var fileURL = window.URL.createObjectURL(file);
        var a = document.createElement("a");
        a.href = fileURL;
        a.download = data.name || "newPDF2";
        document.body.appendChild(a);
        a.click();
        $(window).on('focus', function(e) {
          $('a').remove();
        });
      }
})

这些函数会返回一个pdf文件,但是当我打开pdf文件时,它是空的,似乎在转换过程中丢失了信息。

有人知道为什么会这样吗?

PHP - Web服务代码

$path = "/xxx/xxx/xxx/xxx/work.pdf";
$res = $app->response();
$res['Content-Description'] = 'File Transfer';
$res['Content-Type'] = 'application/force-download';
$res['Content-Type'] = 'application/pdf';
$res['Content-Disposition'] ='attachment; filename=' . basename($path);
$res['Content-Transfer-Encoding'] = 'binary';
$res['Expires'] = '0';
$res['Cache-Control'] = 'must-revalidate';
$res['Pragma'] = 'public';
$res['Content-Length'] = filesize($path);
readfile($path);

2 个答案:

答案 0 :(得分:2)

所以,就像我预期的那样。你们刚刚学会了 - jQuery对于复杂的XHR并不是一个好主意。他们有更多的任务要做,而不是继续实施很少使用的XHR调整。

问题在于,当收到的数据被转换为字符串时,它被转换为UTF-8,长度不断增长并且已损坏:

image description

我们需要获取一个字节数组,我认为这是您尝试使用responseType: "arraybuffer"的内容。但这不应该是一个标题。服务器并没有给出如何转换接收数据的信息。这就是你设置它的方式:

var r = new XMLHttpRequest();
r.open("GET", ".../test.pdf");
// This configures how the data is parsed
r.responseType = "arraybuffer";
r.onload = function() {
  var file = new Blob([this.response], {type: 'application/pdf'});
  var fileURL = window.URL.createObjectURL(file);
  var a = document.createElement("a");
  a.href = fileURL;
  a.download = "newPDF2";
  document.body.appendChild(a);
  a.click();
  $(window).on('focus', function(e) {
    $(a).remove();
  });
}
r.send();

这很有效。此外,如果要设置文件名,请从URL解析它,如下所示:

var file_name = ".../test.pdf".match(/(^|\/)[^/]+$/)[2];

或发送正确的文件名标题并解析它:

var file_name = this.getResponseHeader("Content-Disposition").match(/filename=(.*?)$/)[1];

但是我仍然不明白为什么你不强迫从服务器下载......

答案 1 :(得分:0)

如果没有测试它很难说,但看起来你正在返回实际的PDF,而不是流。试着打开它,就像这样:

window.open("/documents/docDownload");