【问题标题】:Converting ZIP to a Blob将 ZIP 转换为 Blob
【发布时间】:2020-06-15 17:37:57
【问题描述】:

在我们的 Ruby on Rails 应用程序中,我们有一个发送 ZIP 的控制器操作:

send_data File.read(zip_pathname), filename: zip_filename, type: 'application/zip'

我们使用链接上的下载属性使其可下载,如下所示:

<%= link_to zip_download_path(@object), download: zip_filename do %>
  <i class="fas fa-download fa-fw"></i> Download ZIP
<% end %>

效果很好,但可能需要 5-6 秒才能发生任何事情(由于 ZIP 大小)

为了防止用户再次单击链接并显示正在发生的事情,我们尝试使用 AJAX 检索下载,然后将其转换为 Blob 并使用 FileReader 下载它:

const reader = new FileReader();
reader.onload = function(e) {
    const anchor = document.createElement('a');
    anchor.style.display = 'none';
    anchor.href = e.target.result;
    anchor.download = 'download';
    anchor.click();
    hideLoading();
}

$('[download]').on('click', function (e) {
    e.preventDefault();
    showLoading();
    var download = $(this);
    $.get(download.attr('href'), function (data) {
        const blob = new Blob([data], { name: download.attr('download'), type: 'application/zip' });
        reader.readAsDataURL(blob);
    });
});

这成功显示加载屏幕,然后下载 ZIP 并再次隐藏加载屏幕,除了 ZIP 作为下载错误返回,而不是像以前那样实际的 ZIP...看起来 ZIP 转换为一个 Blob 是它失败的地方......

是否可以将 ZIP 转换为 Blob?上面的代码有什么问题吗?

在看:e.target.result内容是:

data:application/zip;base64,...

所以看起来它已经成功创建了数据...但是当我尝试在浏览器窗口中打开它时,它没有显示任何内容...

【问题讨论】:

    标签: download blob filereader


    【解决方案1】:

    如果您通过 ajax 下载非文本文件(如 zip 文件),则必须指定 responseType,即二进制文件,在下面的示例中,我将其设置为 blob,以便您在 ajax 中接收到的数据响应将是一个 blob。
    在锚点中创建并使用 blob url,而不是庞大的数据 uri。

        $.ajax({
            url:download.attr('href'),
            cache:false,
            xhrFields:{
                responseType: 'blob'
            },
            success: function(data){
                var blobUrl = window.URL.createObjectURL(data);
                const anchor = document.createElement('a');
                anchor.style.display = 'none';
                anchor.href = blobUrl;
                anchor.download = 'download.zip';
                anchor.click();
                hideLoading();
            },
            error:function(){
    
            }
        });
    

    此功能需要 jQuery 3+。

    【讨论】:

    • 不错!效果很好......但是出于好奇,这不可能使用 FileReader 方法吗?
    • 你可以,但我不会。它倒退,我们现在可以处理二进制数据。此外,数据 uri 比原始数据大 33%。
    • 好吧,即使我使用更现代的方法,我也更想了解和解决原始问题。
    • 但我选择使用更多的 vanilla JS,因为我们仍然绑定到 jQuery 1.x。
    • 使用原始方法时,问题在于 ajax,您将 zip 文件作为文本获取,这会导致其损坏。当您将它作为 blob 下载时,您仍然可以将 blob 传递给 FileReader 并像以前一样继续。
    【解决方案2】:

    只是想与任何想要在不使用 jQuery3 的情况下执行此操作的人分享...基于 Musa 发布的答案:https://stackoverflow.com/a/60510567/302533

        $('[download]').on('click', function (e) {
            e.preventDefault();
            showFullScreenLoading();
            var $this = $(this);
            var request = new XMLHttpRequest();
            request.open('GET', $this.attr('href'), true);
            request.responseType = 'blob';
            request.onload = function (e) {
                var data = request.response;
                var blobUrl = window.URL.createObjectURL(data);
                var downloadLink = document.createElement('a');
                downloadLink.href = blobUrl;
                downloadLink.download = $this.attr('download') || 'download';
                downloadLink.click();
                hideFullscreenLoading();
            };
            request.send();
        });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-10
      • 2019-03-28
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 2015-03-06
      • 2021-05-25
      • 2015-02-17
      相关资源
      最近更新 更多