【问题标题】:How to create a folder in Firebase Storage using Admin API如何使用 Admin API 在 Firebase Storage 中创建文件夹
【发布时间】:2019-07-22 19:11:48
【问题描述】:

目标:将文件上传到 Firebase 存储中的文件夹中

例如

default_bucket/folder1/file1
default_bucket/folder1/file2
default_bucket/folder2/file3

使用 Firebase 客户端 我可以像这样将文件上传到 Firebase 存储中的文件夹:

    const storageRef = firebase.storage().ref();
    const fileRef = storageRef.child(`${folder}/${filename}`);
    const metadata = {
      contentType: file.type,
      customMetadata: { }
    };
    return fileRef.put(file, metadata);

如果文件夹不存在,则创建它。

但是,我没有设法使用 Admin SDK 在服务器端做同样的事情。

下面的代码,将文件上传到默认存储桶中。

但是,我想将文件上传到默认存储桶中的命名文件夹中。

客户端向 GCF 发出 POST 请求,发送文件和文件夹名称。

Busboy 用于额外的文件夹名称和文件,并将它们传递给上传函数;它上传文件,然后返回一个下载链接。

index.js

const task = require('./tasks/upload-file-to-storage');

app.post('/upload', (req, res, next) => {
  try {
    let uploadedFilename;
    let folder;

    if (req.method === 'OPTIONS') {
      optionsHelper.doOptions(res);
    } else if (req.method === 'POST') {
      res.set('Access-Control-Allow-Origin', '*');

      const busboy = new Busboy({ headers: req.headers });
      const uploads = [];

      busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
        uploadedFilename = `${folder}^${filename}`;

        const filepath = path.join(os.tmpdir(), uploadedFilename);
        uploads.push({ file: filepath, filename: filename, folder: folder });
        file.pipe(fs.createWriteStream(filepath));
      });

      busboy.on('field', (fieldname, val) => {
        if (fieldname === 'folder') {
          folder = val;
        } 
      });

      busboy.on('finish', () => {
        if (uploads.length === 0) {
          res.end('no files found');
        }
        for (let i = 0; i < uploads.length; i++) {
          const upload = uploads[i];
          const file = upload.file;

          task.uploadFile(helpers.fbAdmin, upload.folder, upload.file, uploadedFilename).then(downloadLink => {
            res.write(`${downloadLink}\n`);
            fs.unlinkSync(file);
            res.end();
          });
        }
      });
      busboy.end(req.rawBody);
    } else {
      // Client error - only support POST
      res.status(405).end();
    }
  } catch (e) {
    console.error(e);
    res.sendStatus(500);
  }
});

const api = functions.https.onRequest(app);

module.exports = {
  api
;

上传文件到storage.js

exports.uploadFile = (fbAdmin, folder, filepath, filename) => {
  // get the bucket to upload to
  const bucket = fbAdmin.storage().bucket(); //`venture-spec-sheet.appspot.com/${folder}`

const uuid = uuid();
  // Uploads a local file to the bucket
  return bucket
    .upload(filepath, {
      gzip: true,
      metadata: {
        //destination: `/${folder}/${filename}`,
        cacheControl: 'public, max-age=31536000',
        firebaseStorageDownloadTokens: uuid
      }
    })
    .then(() => {
      const d = new Date();
      const expires = d.setFullYear(d.getFullYear() + 50);

      // get file from the bucket
      const myFile = fbAdmin
        .storage()
        .bucket()
        .file(filename);

      // generate a download link and return it
      return myFile.getSignedUrl({ action: 'read', expires: expires }).then(urls => {
        const signedUrl = urls[0];
        return signedUrl;
      });
    });
};

我已经尝试了一些方法

将存储桶名称设置为默认值和文件夹。这导致了服务器错误。

const bucket = fbAdmin.storage().bucket(`${defaultName}/${folder}`); 

将存储桶名称设置为文件夹。这导致了服务器错误。

const bucket = fbAdmin.storage().bucket(folder); 

而且,我还尝试使用 uploadOptions 的目标属性。 但这仍然会将文件放在默认存储桶中。

    .upload(filepath, {
      gzip: true,
      metadata: {
        destination: `${folder}/${filename}`, // and /${folder}/${filename}
      }
    })

是否可以使用 Admin SDK 上传到文件夹?

例如我想上传一个文件,以便将其放置在一个名为“文件夹”中。

即所以我可以在路径中引用文件:bucket/folder/file.jpg

在下面的示例中,每个“文件夹”都使用 firebase 键命名。

【问题讨论】:

  • 我希望最后一个样本能够工作。它出什么问题了?也许你应该展示整个函数,而不仅仅是一小段代码,因为你可能做错了其他事情。
  • 代码确实远不止这些,但我会添加它以防万一。
  • 完整的代码看起来仍然不像定义 Cloud Functions 触发器。从触发器本身的角度来看,您可能做错了什么。 MCVE,请。还请说明代码实际在做什么,这与您的预期不同。
  • @DougStevenson 嗨,Doug,我现在添加了完整的代码和更多上下文。感谢您对此的帮助。
  • 您似乎对“桶”和“文件夹”之间的区别感到困惑。桶在所有 GCS 中都有唯一的名称。您不能随时创建一个新的存储桶名称 - 您必须在控制台或使用 gsutil 创建。此外,GCS 上并没有真正的“文件夹”之类的东西。只有文件的路径组件看起来像文件夹。

标签: firebase firebase-storage firebase-admin


【解决方案1】:

发现问题。 我愚蠢地在错误的地方声明了目的地选项。

而不是在元数据对象中:

 return bucket
    .upload(filepath, {
      gzip: true,
      metadata: {
        destination: `${folder}/${filename}`,
        cacheControl: 'public, max-age=31536000',
        firebaseStorageDownloadTokens: uuid
      }
    })

它应该在选项对象上:

 return bucket
    .upload(filepath, {
      gzip: true,
      destination: `${folder}/${filename}`,
      metadata: {   
        cacheControl: 'public, max-age=31536000',
        firebaseStorageDownloadTokens: uuid
      }
    })

进行此更改后,文件现在被上传到一个命名的“文件夹”中。

【讨论】:

    【解决方案2】:

    在存储控制台中,除了Upload File 按钮之外,还有一个create folder 选项用于存储桶。可以在存储桶中创建文件夹并在控制台上将文件上传到它。要使用管理 API 在存储桶中创建此类文件夹,请在文件引用之前添加文件夹。例如

    const blob = bucket.file('folder1/folder2/' + req.file.originalname);
    

    【讨论】:

      猜你喜欢
      • 2020-01-05
      • 1970-01-01
      • 2019-01-16
      • 2020-11-27
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 2016-10-06
      • 2021-12-07
      相关资源
      最近更新 更多