【问题标题】:How to take a list of DownloadURLs and donwload a .ZIP folder of all the files from Firebase Storage如何获取下载 URL 列表并从 Firebase 存储中下载所有文件的 .ZIP 文件夹
【发布时间】:2019-08-19 14:01:23
【问题描述】:

我的 Firebase 存储分区的文件夹和子文件夹中有很多文件。 我的实时 Firebase 数据库中有所有这些文件的 DownloadURL 列表。 我正在尝试进行批量下载,最好创建一个 .ZIP 文件夹供最终用户立即下载。

其他一些帖子(例如How to download entire folder from Firebase Storage?)请注意,没有内置API 可以进行批量下载,例如从存储桶下载整个文件夹。据我所知,这并没有改变。

然而,一个相关的答案 (How to download entire folder from Firebase Storage?) 建议创建一个 .ZIP 文件夹是可能的,但没有详细说明如何。

我怎么能...

... A) 在客户端使用纯JS,让最终用户收集所有DownloadURLs并一次下载文件?...

...或...

... B) 使用用 Node.JS 编写的云函数来使用 DownloadURLs 创建一个 .ZIP 文件,最终用户可以将其作为一个文件下载。 (我假设一个 .ZIP 文件可以作为另一个文件存储在存储桶中,并具有自己的 DownloadURL 并像任何其他文件一样下载,然后在本地解压缩并提取所有原始文件。如果这不是,请纠正我案例)

... 或者这些方法都不可行?如果不是为什么,缺少什么功能?

提前感谢您的任何见解!

【问题讨论】:

  • 您找到解决方案了吗?
  • 也想知道!

标签: node.js firebase firebase-storage


【解决方案1】:

迟到总比不到好,您可以使用JSZip,它提供了一个简单的 API 用法。

生成 zip 文件后,您可以使用FileSaver 保存/下载它。

这就是我生成 zip 文件的方式(从客户端)

import JSZip from "jszip";
import saveAs from "file-saver";

generateZipFile(photosToDownload) {

  var jszip = new JSZip();

  //Looping through to get the download url for each image
  for (let i = 0; i < photosToDownload.length; i++) {
    let photoName = photosToDownload[i].photo_image_name;
    let photoImageURL = photosToDownload[i].generated_image_url;

    let photoImageExtension = photoName.substr(photoName.length - 4);

    jszip.file(
      photoName + photoImageExtension, //in my case, this produces something like 'my image.jpg'
      this.downloadUrlAsPromise(photoImageURL) //generates the file we need to download
    );

    //If we have reached the last image in the loop, then generate the zip file
    if (i == photosToDownload.length - 1) {
      jszip.generateAsync({ type: "blob" }).then(function(content) {
        saveAs(content, "MyZipFile.zip");
      });
    }
  }
},

downloadUrlAsPromise(url) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", url, true);
    xhr.responseType = "arraybuffer";
    xhr.onreadystatechange = function(evt) {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(xhr.response);
        } else {
          reject(new Error("Error for " + url + ": " + xhr.status));
        }
      }
    };
    xhr.send();
  });
}, 

【讨论】:

    【解决方案2】:

    这是一个简单的带有 ESNext 语法的 TypeScript 代码示例,它使用上面@Oush 提到的相同包:

    import JSZip from 'jszip';
    import firebase from 'firebase/app';
    import { saveAs } from 'file-saver';
    
    export const downloadFolderAsZip = async (folderPath: string) => {
        const jszip = new JSZip();
        const folderRef = firebase.storage().ref(folderPath);
        const files = (await folderRef.listAll()).items;
        const downloadUrls: Array<string> = await Promise.all(
            files.map(({ name }) => folderRef.child(name).getDownloadURL())
        );
        const downloadedFiles = await Promise.all(downloadUrls.map(url => fetch(url).then(res => res.blob())));
        downloadedFiles.forEach((file, i) => jszip.file(files[i].name, file));
        const content = await jszip.generateAsync({ type: 'blob' });
        saveAs(content, folderPath);
    };
    

    请注意,您必须 configure CORS for Cloud Storage first 这样才能正常工作。默认情况下,Cloud Storage 没有 CORS 配置(您可以使用gsutil cors get gs://your-bucket-name.appspot.com 命令查找),因此浏览器将拒绝fetch() 调用,因为 gcs 没有返回 CORS 标头。

    进一步阅读:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 2017-07-08
      • 1970-01-01
      相关资源
      最近更新 更多