29

我正在尝试了解 HTML5 API。我正在设计浏览器客户端需要从服务器下载多个文件的 Web 应用程序;用户将使用下载的文件和应用程序执行某些操作,而不是将状态保存在用户硬盘上。我知道浏览器只能将这些文件保存到其沙箱中,只要用户可以在第二次启动应用程序时检索这些文件就可以了。我应该使用 BlobBuilder 还是 FileSaver?我在这里有点迷路了。

4

3 回答 3

67

我将向您展示如何使用XMLHttpRequest Level 2下载文件并使用FileSystem APIFileSaver 接口保存它们。

##下载文件##

要下载文件,您将使用 XMLHttpRequest Level 2(又名 XHR2),它支持跨域请求、上传进度事件以及上传/下载二进制数据。在“ XMLHttpRequest2 中的新技巧”一文中,有很多使用 XHR2 的示例。

要将文件下载为 blob,您只需指定responseType“blob”即可。您还可以使用“text”、“arraybuffer”或“document”类型。下面的函数下载 中的文件url并将其发送到success回调:

function downloadFile(url, success) {
    var xhr = new XMLHttpRequest(); 
    xhr.open('GET', url, true); 
    xhr.responseType = "blob";
    xhr.onreadystatechange = function () { 
        if (xhr.readyState == 4) {
            if (success) success(xhr.response);
        }
    };
    xhr.send(null);
}

回调将success接收 Blob 实例作为参数,该实例可以稍后修改、保存和/或上传到服务器。

##使用文件系统 API 保存文件##

正如Can i use...网站指出的那样,支持 FileSystem API 的浏览器并不多。对于 Firefox ,有一个缺乏支持的解释。因此,您将不得不使用 Chrome 来执行此操作。

首先,您必须请求一个存储空间,它可以是临时的,也可以是持久的。您可能希望拥有一个持久存储,在这种情况下,您将需要预先请求一个存储空间配额(一些事实):

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.storageInfo = window.storageInfo || window.webkitStorageInfo;

// Request access to the file system
var fileSystem = null         // DOMFileSystem instance
    , fsType = PERSISTENT       // PERSISTENT vs. TEMPORARY storage 
    , fsSize = 10 * 1024 * 1024 // size (bytes) of needed space 
;
    
window.storageInfo.requestQuota(fsType, fsSize, function(gb) {
    window.requestFileSystem(fsType, gb, function(fs) {
        fileSystem = fs;
    }, errorHandler);
}, errorHandler);

现在您可以访问文件系统,您可以从中保存和读取文件。下面的函数可以将指定路径中的 blob 保存到文件系统中:

function saveFile(data, path) {
    if (!fileSystem) return;
    
    fileSystem.root.getFile(path, {create: true}, function(fileEntry) {
        fileEntry.createWriter(function(writer) {
            writer.write(data);
        }, errorHandler);
    }, errorHandler);
}

并通过其路径读取文件:

function readFile(path, success) {
    fileSystem.root.getFile(path, {}, function(fileEntry) {
        fileEntry.file(function(file) {
            var reader = new FileReader();

            reader.onloadend = function(e) {
                if (success) success(this.result);
            };

            reader.readAsText(file);
        }, errorHandler);
    }, errorHandler);
}

除了readAsText方法之外,根据FileReader API可以调用readAsArrayBufferreadAsDataURL.

##使用文件保护程序##

在客户端保存生成的文件”一文很好地解释了这个 API 的使用。某些浏览器可能需要FileSaver.js才能拥有该saveAs界面。

如果你将它与downloadFile函数一起使用,你可以有这样的东西:

downloadFile('image.png', function(blob) {
    saveAs(blob, "image.png");
});

当然,如果用户可以可视化图像,对其进行操作然后将其保存在他的驱动器中,那将更有意义。

###错误处理程序###

只是为了完成这个例子:

function errorHandler(e) {
    var msg = '';

    switch (e.code) {
        case FileError.QUOTA_EXCEEDED_ERR:
            msg = 'QUOTA_EXCEEDED_ERR';
            break;
        case FileError.NOT_FOUND_ERR:
            msg = 'NOT_FOUND_ERR';
            break;
        case FileError.SECURITY_ERR:
            msg = 'SECURITY_ERR';
            break;
        case FileError.INVALID_MODIFICATION_ERR:
            msg = 'INVALID_MODIFICATION_ERR';
            break;
        case FileError.INVALID_STATE_ERR:
            msg = 'INVALID_STATE_ERR';
            break;
        default:
            msg = 'Unknown Error';
            break;
    };

    console.log('Error: ' + msg);
}

##有用的链接##

于 2012-12-08T16:24:50.723 回答
2

如果您只支持 HTML5 浏览器,则可以使用“下载”属性。更多细节在这里:http ://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

于 2013-08-24T02:48:51.030 回答
1

我的技巧是简单地将 IFRAME 附加一个指向您的多个下载的“src”属性。服务器站点应发送带有“处置:附件”标头的文件,然后客户端将尝试将文件存储在本地。唯一的“问题”是 IFRAME 将作为碎片留在您的 DOM 树中,直到用户离开或重新加载页面。使 IFRAME 不可见(例如 width=0;height=0;),您就可以开始了!所有浏览器。

于 2015-08-04T19:49:55.750 回答