HTML5 File API从服务器下载文件并将其保存在沙箱中

时间:2012-12-06 21:31:46

标签: html5 blob fileapi filesaver.js

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

3 个答案:

答案 0 :(得分:65)

我将向您展示如何使用XMLHttpRequest Level 2下载文件,并使用FileSystem APIFileSaver interface保存文件。

正在下载文件

要下载文件,您将使用XMLHttpRequest Level 2(又名XHR2),它支持跨源请求,上传进度事件以及上载/下载二进制数据。在帖子“New Tricks in 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实例作为参数,以后可以修改并保存和/或上传到服务器。

使用FileSystem API保存文件

由于我可以使用网站points out,因此没有很多浏览器支持FileSystem API。对于Firefox there's an explanation缺乏支持。因此,您必须使用Chrome才能执行此操作。

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

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

使用FileSaver

帖子“Saving Generated Files on Client-Side”很好地解释了此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);
}

有用的链接

答案 1 :(得分:2)

如果您只支持HTML5浏览器,则可以下载"下载"你可以使用的属性。更多详情:http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

答案 2 :(得分:0)

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