【问题标题】:Zero btye file written to Firebase storage写入 Firebase 存储的零字节文件
【发布时间】:2021-09-04 12:03:00
【问题描述】:

我正在将文件从 vuejs 应用程序上传到 firebase 存储。我可以成功写入 firebase 存储,但文件的字节数为零。

文件通过 GraphQL 突变发送到后端:

uploadStream: {
  type: GraphQLBoolean,
  args: {
    id: {
      type: GraphQLString
    },
    file: {
      type: GraphQLUpload
    }
  },
  // eslint-disable-next-line no-unused-vars
  resolve: async (root, { id, file }, context) => {
    const { filename, mimetype, createReadStream } = await file
    const stream = createReadStream()
    const ext = filename.substr(filename.lastIndexOf('.') + 1)
    storageService.upload(id, ext, mimetype, stream)
  }
}

我这样写到存储中:

const upload = async (filename, ext, mimetype, stream) => {
  const metadata = {
    metadata: {
      // This line is very important. It's to create a download token.
      firebaseStorageDownloadTokens: uuid()
    },
    contentType: mimetype
  }
  filename = `profiles/${filename}.${ext}`
  stream.pipe(
    bucket
      .file(filename, {
        gzip: true,
        metadata: metadata
      })
      .createWriteStream()
      .end()
  )
}

我使用 firebase-admin SDK 正在检索存储桶:

const firebaseConfig = {
  credential: firebase.credential.cert(JSON.parse(firebase_credential)),
  databaseURL: firebase_db,
  storageBucket: firebase_storage
}

firebase.initializeApp(firebaseConfig)

const db = firebase.firestore()
const bucket = firebase.storage().bucket()

我不明白为什么上面的代码将零字节文件写入存储。

【问题讨论】:

    标签: javascript node.js firebase google-cloud-storage firebase-storage


    【解决方案1】:

    创建到 Cloud Storage 的写入流后,立即将其关闭。

    bucket
      .file(filename, {
        gzip: true,
        metadata: metadata
      })
      .createWriteStream()  // <- opens write stream
      .end()                // <- immediately closes it
    

    如果stream 和存储文件的流具有"error" 事件的侦听器,那么您早就发现了这一点。

    只需删除.end(),您的代码就会再次运行:

    const upload = async (filename, ext, mimetype, stream) => {
      const metadata = {
        metadata: {
          // This line is very important. It's to create a download token.
          firebaseStorageDownloadTokens: uuid()
        },
        contentType: mimetype
      }
      filename = `profiles/${filename}.${ext}`
      stream.pipe(
        bucket
          .file(filename, {
            gzip: true,
            metadata: metadata
          })
          .createWriteStream()
      )
    }
    

    但是,由于您在 upload() 方法上使用了 async,这意味着您希望它返回一个 Promise,它在上传完成时解析或在上传失败时拒绝。

    const upload = async (filename, ext, mimetype, stream) => {
      const metadata = {
        metadata: {
          // This line is very important. It's to create a download token.
          firebaseStorageDownloadTokens: uuid()
        },
        contentType: mimetype
      }
      filename = `profiles/${filename}.${ext}`
    
      const storageStream = bucket
        .file(filename, {
          gzip: true,
          metadata: metadata
        })
        .createWriteStream();
    
      return new Promise((resolve, reject) => {
        storageStream.once("finish", resolve); // resolve when written
        storageStream.once("error", reject);   // reject when either stream errors
        stream.once("error", reject);
    
        stream.pipe(storageStream);            // pipe the data
      });
    }
    

    这意味着resolve: 需要更新为:

    resolve: async (root, { id, file }, context) => {
      const { filename, mimetype, createReadStream } = await file
      const stream = createReadStream()
      const ext = filename.substr(filename.lastIndexOf('.') + 1)
      return storageService.upload(id, ext, mimetype, stream)
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-19
      • 2022-11-02
      • 2012-07-13
      • 1970-01-01
      • 2017-07-11
      • 1970-01-01
      • 2019-12-25
      • 2016-02-13
      • 1970-01-01
      相关资源
      最近更新 更多