使用Cloud Functions如何删除文件?

20

当我在Firebase数据库中删除帖子时,我希望云函数能够相应地删除Firebase存储中的缩略图。我的问题是,当我尝试删除缩略图时,我认为没有正确找到图像文件。

这是我尝试过的方法:

const functions = require('firebase-functions')
const admin = require('firebase-admin')
const gcs = require('@google-cloud/storage')()

exports.deletePost = functions.database.ref('Posts/{pushId}').onWrite(event => {

  const original = event.data.val()
  const previous = event.data.previous.val()
  const pushId = event.params.pushId

  if (original === null)
    return

  const filePath = 'Posts/' + pushId + 'thumbnail.jpg'
  const bucket = gcs.bucket('postsapp-12312')
  const file = bucket.file(filePath)
  const pr = file.delete()


  return pr
});

这是我在日志中看到的信息:

ApiError:未找到 在 Object.parseHttpRespBody (/user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:192:30) 在 Object.handleResp (/user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:132:18) 在 /user_code/node_modules/@google-cloud/storage/node_modules/@google-cloud/common/src/util.js:465:12 在 Request.onResponse [as _callback] (/user_code/node_modules/@google-cloud/storage/node_modules/retry-request/index.js:120:7) 在 Request.self.callback (/user_code/node_modules/@google-cloud/storage/node_modules/request/request.js:188:22) 在 emitTwo (events.js:106:13) 在 Request.emit (events.js:191:7) 在 Request. (/user_code/node_modules/@google-cloud/storage/node_modules/request/request.js:1171:10) 在 emitOne (events.js:96:13) 在 Request.emit (events.js:188:7)


require 调用 gcs,对我而言只有这个有效:const gcs = require('@google-cloud/storage');,感谢:https://dev59.com/llgR5IYBdhLWcg3wbcv1#41352560 - Gene Bo
5个回答

16

如果还有其他人仍然感到困惑,我成功地将我的内容删除,方法是排除存储桶名称(从而选择默认的 Firebase 存储桶):

 const bucket = admin.storage().bucket();
 const path = "path/to/file.wav";
 return bucket.file(path).delete();

7
我已经成功修复了它。问题在于我错误地编写了我的存储桶地址;它应该像postsapp-12312.appspot.com而不是postsapp-12312更新 为了更好地放置您的存储桶地址,请参考@Robert答案

你用来删除的是GCS而不是Firebase函数。你正在使用函数来监听数据库更改并通过GCS进行删除。 - vzhen
@vzhen 是的,那时候这是唯一的方法,现在有没有改变呢?你能提供一个更好的答案吗? - Faisal
我也在寻找解决方法。我正在使用Firebase Storage而不是GCS。似乎Firebase Admin SDK Storage不支持服务器端删除。 - vzhen
哦,我的错,所以你正在使用GCS来删除Firebase存储文件。你在数据库中存储了下载URL的引用吗? - vzhen
是的,但在我的情况下有所不同。引用基于用户uid + 帖子密钥 + 生成的密钥构建。它们都在帖子节点中可用,因此我从那里构建了downloadURL。 - Faisal
显示剩余4条评论

6

看一下我使用的这些函数

const app = admin.initializeApp();

export const onDeleteItem = 
 functions.firestore.document('collectionItems/{collectionID}/items/{itemID}')
   .onDelete((snap, context) => {
     const { collectionID } = context.params;
     const { itemID } = context.params
     return deleteItemImage(collectionID, itemID)
     }
 )

async function deleteItemImage(collectionID: string, itemID: string) {
  const path = `images/${collectionID}/${itemID}`;
  const bucket = app.storage().bucket();
  return bucket.file(path).delete()
    .then(function () {
      console.log(`File deleted successfully in path: ${path}`)
    })
    .catch(function (error) {
      console.log(`File NOT deleted: ${path}`)
    })
}

5
您可以使用 Firebase 函数环境配置来获取存储桶名称:
const bucket = gcs.bucket(functions.config().firebase.storageBucket)

这是一个更好的方法。非常感谢您,先生。 - Faisal

3
据我所知,无法在云函数内删除Firebase存储文件。您可以监听存储桶上的更改事件,但无法与其交互。
我的解决方法是使用`.set(null)`从数据库中移除“post”。当promise解析时,您可以使用它来调用Firebase存储的删除操作。
firebase.database().ref('Posts/{pushId}').set(null).then(() => {
  console.log('Post deleted from database')
  firebase.storage().ref(`Posts/${pushId}thumbnail-image.jpg`).delete().then(() => {
    console.log('Successfully deleted thumbnail');
  }).catch(err => {
    console.log(err);
  });
}).catch(err => {
  console.log(err);
});

Firebase 存储不支持递归删除整个存储桶,因此您需要逐个删除每个文件。

1
实际上,你可以使用我正在使用的函数file.delete()。问题在于我写错了我的存储桶地址。它应该是postsapp-12312.appspot.com而不是postsapp-12312。很抱歉我没有发布正确的答案。 - Faisal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接