AJAX响应提供了损坏的压缩(.tgz)文件

时间:2013-11-29 14:08:11

标签: javascript ajax compression download gunzip

我们正在实现一个客户端Web应用程序,它通过XMLHttpRequests(和AJAX引擎)专门与服务器通信。

XHR响应通常是纯文本,上面有一些XML,但在这种情况下,服务器正在发送.tgz文件类型的压缩数据。我们确信服务器正在发送的数据是正确的,因为如果我们使用诸如curl的HTTP命令行客户端,则作为响应发送的文件是有效的并且包含预期的数据。

但是,当在可下载文件中进行AJAX调用并“响应”响应时,我们获得的文件大小(高于)正确的文件,并且解析器无法识别它。它给出以下错误:

gzip: stdin: not in gzip format
/bin/gtar: Child returned status 1
/bin/gtar: Error is not recoverable: exiting now

我正在使用的代码如下:

*$.AJAX*.done(function(data){
    window.URL = window.webkitURL || window.URL;
    var contentType = 'application/x-compressed-tar';
    var file = new Blob([data], {type: contentType});
    var a = document.createElement('a'),
    ev = document.createEvent("MouseEvents");
    a.download = "browser_download2.tgz";
    a.href = window.URL.createObjectURL(file);
    ev.initMouseEvent("click", true, false, self, 0, 0, 0, 0, 0,
            false, false, false, false, 0, null);
    a.dispatchEvent(ev);
});

我避免了用于进行AJAX调用的参数,但我们假设这不是问题,因为我正确地收到了答案。我使用了这个contentType,因为它与curl获得的相同,但我尝试了不同的内容。代码可能看起来有点奇怪,所以我会为你解毒它:我基本上是创建一个链接,我附加了它的下载链接和文件的名称(这是一个肮脏的方式来命名文件)。最后,我实际上是点击链接。

我将正确的tgz文件和通过浏览器获得的文件与十六进制查看器进行了比较,我观察到了损坏的文件(EF,BF和BD,整个文件中)中的模式重复,这些模式在正确的文件中不存在

因此我想到了一些可能的原因:

  

(a)浏览器正在添加额外的字符或响应   标头仍在下载的文件中。

     

(b)文件已部分解压缩,因为我检查时   请求标题我可以说“Accept-Encoding:gzip,deflate”;   虽然我不知道浏览器(在我的情况下是Firefox)   自动解压缩数据。

     

(c)我用来填充数据的代码不正确;虽然   它在另一个文件中使用普通/文本文件很好地完成了目标   场合。

修改

我还为您提供了十六进制检查的链接:

(a)文件损坏:http://en.webhex.net/view/278aac05820c34dfbdd2217c03970dd9/0 (b)(推测)正确的文件:http://en.webhex.net/view/4a01894b814c17d2ec71ba49ac48e683

1 个答案:

答案 0 :(得分:13)

我不知道这个帖子是否会对某人有所帮助,但以防我找出问题的原因和解决办法。

原因

默认Javascript变量以Unicode / ASCII格式存储信息;他们没有准备好正确存储二进制数据,这就是为什么人们可以很容易地看到解释错误的字符(这也解释了为什么在Hex Viewer中观察到EF,BF等的重复,这代表了ASCII / Unicode的错误字符) 。

解决方案

最后一个浏览器版本实现了所谓的类型化数组。它们是javascript数组,可以以不同的格式(也是二进制)存储数据。然后,如果指定XMLHttpRequest响应是二进制格式,则数据将被正确存储,并且当blob到文件中时,文件不会被破坏。看看我使用的代码:

var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.responseType = 'arraybuffer';

请注意,关键点是将responseType定义为“arraybuffer”。也许有趣的是注意到我决定不再使用Jquery作为AJAX了。它很难实现这个功能,我为解析Jquery所做的所有尝试都是徒劳的(在我的情况下,其他地方描述的overrideMimeType不起作用)。相反,旧的纯XMLHttRquest工作得非常好。