简体   繁体   English

NextJS 文件上传到谷歌云存储成功但总是上传 0 字节文件 - 使用强大

[英]NextJS file upload to Google Cloud Storage successful but always uploading 0 byte file - using formidable

Im trying to implement a fileupload in nextJS and stream files to google cloud storage.我试图在 nextJS 和 stream 文件中实现文件上传到谷歌云存储。 I'm using formidab.我正在使用强大的。 Formidable is giving me a filepath, newFilename, filesize, etc but when the file showing up in google storage it has zero bytes. Formidable 给了我一个文件路径、新文件名、文件大小等,但是当文件出现在谷歌存储中时,它的字节数为零。 It's like the location is being created but my blob stream isn't actually pushing the file there.这就像正在创建位置,但我的 blob stream 实际上并没有将文件推送到那里。

Below is code from my api route.下面是我的 api 路线的代码。 Any ideas?有任何想法吗?

import { Storage } from "@google-cloud/storage";
import formidable from '../../lib/formidable-serverless'

export const config = {
  api: {
    bodyParser: false,
  },
};

export default async function handler(req, res) {
  console.log('req')
  const storage = new Storage({
    projectId: process.env.GOOGLE_SERVICE_ID,
    client_email: process.env.GOOGLE_CLIENT_EMAIL,
    private_key: process.env.GOOGLE_SERVICE_KEY,
  });
  const data = await new Promise(function(resolve, reject) { 
    const form = new formidable.IncomingForm();
    form.keepExtensions = true;
    form.parse(req, function(err, fields, files) {
      if (err) return reject(err);
      resolve({ fields, files });
    });
  });
  const file = data.files.file
    try {
      const bucket = storage.bucket(process.env.GCS_BUCKET)
      const blob = bucket.file(file.originalFilename);
     
      const blobStream = blob.createWriteStream({
        resumable: false,
      });
    
      blobStream.on("error", (err) => {
        console.log('ERR', err.message)
        res.status(500).send({ message: err.message });
      });
  
      blobStream.on("finish", async () => {
        const publicURL = `https://storage.googleapis.com/${bucket.name}/${blob.name}`
      ;
        try {
          await blob.makePublic();
        } catch {
          return res.status(500).send({
            message: `Uploaded the file successfully: ${file.newFilename}, but public access is denied!`,
            url: publicURL,
          });
        }
  
        res.status(200).send({
          message: "Uploaded the file successfully: " + file.newFilename,
          url: publicURL,
        });
      });
      blobStream.end();
    } catch (err) {
      if (err.code == "LIMIT_FILE_SIZE") {
        console.log('ERR', err.message)
        return res.status(500).send({
          message: "File size cannot be larger than 25MB!",
        });
      }
  
      res.status(500).send({
        message: `Could not upload the file: ${file.newFilename}. ${err}`,
      });
   }

This is what my blobstream looks like immediately after creating it.这是我的 blobstream 创建后的样子。

Writable {
  _writableState: WritableState {
    objectMode: false,
    highWaterMark: 16384,
    finalCalled: false,
    needDrain: false,
    ending: false,
    ended: false,
    finished: false,
    destroyed: false,
    decodeStrings: true,
    defaultEncoding: 'utf8',
    length: 0,
    writing: false,
    corked: 0,
    sync: true,
    bufferProcessing: false,
    onwrite: [Function: bound onwrite],
    writecb: null,
    writelen: 0,
    afterWriteTickInfo: null,
    buffered: [],
    bufferedIndex: 0,
    allBuffers: true,
    allNoop: true,
    pendingcb: 0,
    prefinished: false,
    errorEmitted: false,
    emitClose: true,
    autoDestroy: true,
    errored: null,
    closed: false
  },

And this is what the file looks like after formidable promise is resolved.这就是强大的 promise 解决后文件的样子。 There is also a writable stream there as well.那里还有一个可写的 stream。

PersistentFile {
  _events: [Object: null prototype] { error: [Function (anonymous)] },
  _eventsCount: 1,
  _maxListeners: undefined,
  lastModifiedDate: 2022-11-22T14:54:26.597Z,
  filepath: '/var/folders/yb/l636l56d7ng731jp24crv6lw0000gn/T/9e8fb9b8b1e0740b2622b990b',
  newFilename: '9e8fb9b8b1e0740b2622b990b',
  originalFilename: '17.mp3',
  mimetype: 'audio/mpeg',
  hashAlgorithm: false,
  size: 7020751,
  _writeStream: WriteStream {
    _writableState: WritableState {
      objectMode: false,
      highWaterMark: 16384,
      finalCalled: true,
      needDrain: true,
      ending: true,
      ended: true,
      finished: true,
      destroyed: true,
      decodeStrings: true,
      defaultEncoding: 'utf8',
      length: 0,
      writing: false,...
}

Am i somehow not passing my file into the writestream when i create my blob?当我创建我的 blob 时,我是否以某种方式没有将我的文件传递到 writestream 中?

Answering as a Community wiki,作为社区维基回答,

This can be solved by implementing a readStream that read the file path where formidable was temporarily storing the file before the writestream began.这可以通过实现一个readStream来解决,该 readStream 读取 formidable 在writestream开始之前临时存储文件的文件路径。

createReadStream(file.filepath) 
.pipe(blob.createWriteStream(file.originalFilename, file.mimetype))  
console.log('blobstream', blobStream) 
.on("error", (err) => { console.log('ERR', err.message) 
res.status(500).send({ message: err.message 
});
}) 
.on("finish", async () => { // create a url to access file ... 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM