BlobBuilder破坏二进制数据

时间:2011-05-29 21:07:37

标签: javascript html5 google-chrome-extension blob

我遇到BlobBuilder(Chrome11)的问题 我尝试使用XHR请求从服务器获取图像。然后我尝试使用BlobBuilder / FileWriter将其保存到本地FS。互联网上的每个例子都是关于使用text / plain mime类型,这些例子工作得很好。但是当我尝试编写使用XHR获得的二进制数据时,文件大小比原始文件大小大约1.5-2倍。它无法在Picasa / Eye Of Gnome中查看。

var xhr = new XMLHttpRequest();
var photoOrigUrl = 'http://www.google.ru/images/nav_logo72.png';
xhr.open('GET', photoOrigUrl, true);
xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        var contentType = xhr.getResponseHeader('Content-type');

        fsLink.root.getFile('nav_logo72.png', {'create': true}, function(fileEntry) {
            fileEntry.createWriter(function(fileWriter) {
                var BlobBuilderObj = new (window.BlobBuilder || window.WebKitBlobBuilder)();
                BlobBuilderObj.append(xhr.responseText);

                fileWriter.write(BlobBuilderObj.getBlob(contentType));
            }, function(resultError) {
                console.log('writing file to file system failed (   code ' + resultError.code + ')');
            });
        });
    }
}

xhr.send();

存在fsLink,这是扩展名。

5 个答案:

答案 0 :(得分:15)

问题是BlobBuilder.append(xhr.responseText)将其参数检测为UTF-8字符串,这是XHR返回的字符串,而不是二进制数据,这就是它的真实含义。有一些技巧可以让BlobBuilder将其读取为二进制数据而不是字符串数据:

var xhr = new XMLHttpRequest();
var photoOrigUrl = 'http://www.google.ru/images/nav_logo72.png';
xhr.open('GET', photoOrigUrl, true);

// CHANGE 1: This stops the browser from parsing the data as UTF-8:
xhr.overrideMimeType('text/plain; charset=x-user-defined');

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        var contentType = xhr.getResponseHeader('Content-type');

        fsLink.root.getFile('nav_logo72.png', {'create': true}, function(fileEntry) {
            fileEntry.createWriter(function(fileWriter) {

                // CHANGE 2: convert string object into a binary object
                var byteArray = new Uint8Array(xhr.response.length);
                for (var i = 0; i < xhr.response.length; i++) {
                    byteArray[i] = xhr.response.charCodeAt(i) & 0xff;
                }

                var BlobBuilderObj = new (window.BlobBuilder || window.WebKitBlobBuilder)();

                // CHANGE 3: Pass the BlobBuilder an ArrayBuffer instead of a string
                BlobBuilderObj.append(byteArray.buffer);

                // CHANGE 4: not sure if it's needed, but keep only the necessary
                // part of the Internet Media Type string
                fileWriter.write(BlobBuilderObj.getBlob(contentType.split(";")[0]));
            }, function(resultError) {
                console.log('writing file to file system failed (   code ' + resultError.code + ')');
            });
        });
    }
}

xhr.send();

这给了我一个与xhr.getResponseHeader('Content-Length')建议的长度相同的文件。

答案 1 :(得分:3)

您可以使用xhr.responseType='arraybuffer'

BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;

var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png', true);
xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
  if (this.status == 200) {
    var bb = new BlobBuilder();
    bb.append(this.response); // Note: not xhr.responseText

    var blob = bb.getBlob('image/png');
    ...
  }
};

xhr.send();

答案 2 :(得分:1)

我认为Stoive是现货,但我想指出的是,现在有Blob构造函数可用,而不是BlobBuilder

 var b = new Blob([byteArray.buffer], {'type': 'application/type'});

我认为这更符合现行标准。非常感谢Stoive,非常有帮助。

答案 3 :(得分:0)

Btw XHR2为实现我的任务设置了更好的方法:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.google.ru/images/nav_logo72.png', true);
xhr.responseType = 'blob';

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        // xhr.responseBlob is needed blob data
    }
}

xhr.send();

唯一令人失望的是,这仍然是Chrome中的一个错误:http://code.google.com/p/chromium/issues/detail?id=52486

答案 4 :(得分:0)

XMLHttpRequest无法加载http://www.google.ru/images/nav_logo72.png。原始文件:// Access-Control-Allow-Origin不允许。