如何获取DownloadURL列表并从Firebase Storage下载所有文件的.ZIP文件夹

时间:2019-03-28 17:32:04

标签: node.js firebase firebase-storage

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

其他几篇文章(例如How to download entire folder from Firebase Storage?)指出,没有内置的API可以进行批量下载,例如从存储桶中下载整个文件夹。据我所知,这并没有改变。

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

我怎么能...

... A)在客户端使用纯JS允许最终用户收集所有DownloadURL并立即下载文件?...

...或...

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

...还是这些方法都不可行?如果不是原因,缺少什么功能?

在此先感谢您提供任何见解!

2 个答案:

答案 0 :(得分:0)

迟到总比没有好,您可以使用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();
  });
}, 

答案 1 :(得分:0)

这里是一个简单的 TypeScript 代码示例,使用 ESNext 语法,使用上面@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);
};

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

进一步阅读: