【问题标题】:HTML5 File API downloading file from server and saving it in sandboxHTML5 File API 从服务器下载文件并将其保存在沙箱中
【发布时间】:2012-11-25 00:50:26
【问题描述】:

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

【问题讨论】:

    标签: html blob fileapi filesaver.js


    【解决方案1】:

    我将向您展示如何使用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 支持文件系统 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);
    }
    

    ##有用的链接##

    【讨论】:

    【解决方案2】:

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

    【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-15
      相关资源
      最近更新 更多