如何将 File 对象转为 Sharp 能够理解的缓冲区?

问题描述 投票:0回答:2

我有一个

File
类型的对象,它由 Node.js 后端处理。

export default function handler(req: NextRequest, res: NextResponse<Object>) {
  console.log("METHOD: ", req.method)
  if (req.method == "POST") {
    const form = new Formidable.IncomingForm()
    form.parse(req, (error: any, fields: any, files: any) => {
      console.log(fields)
      console.log(files.image)
      await Sharp(Buffer.from(files.image))
        .toFormat("webp")  
        .toFile("save.webp")
    })

    res.status(200).send({ message: "Success" })
  } else {
    res.status(404).send({ message: "POST only supported" })
  }
}

files.image
的类型为
File
,当我尝试将其传递到
Buffer.from()
时,我会收到错误

The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of File  

我尝试传入

await Sharp(Buffer.from(files.image, 'base64'))
但出现同样的错误。有什么办法可以把
files.image
变成 Buffer Sharp 可以理解的吗?

更新:我找到了一种通过使用以下方法来实现我的目标的方法:

if (req.method == "POST") {
    const form = new Formidable.IncomingForm()
    form.parse(req, (error: any, fields: any, files: any) => {

      // Pass in the temp file location where the incoming form stores the request  
      ConvertToWebP(files.image.path)  
    })

    res.status(200).send({ message: "Success" })
  } else {
    res.status(404).send({ message: "POST only supported" })
  }
}

经过几个小时的不同方法后,我通过查看

File
对象发现了这一点:

{
  image: File {
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    size: 481,
    path: 'C:\\XXX\\XXX\\AppData\\Local\\Temp\\upload_XXX',
    name: 'eagle.png',
    type: 'image/png',
    hash: null,
...

注意:我想保持这个问题的开放性,因为这个解决方法可能有效,但我仍然想了解为什么我不能传入 Buffer 对象。

javascript node.js form-data sharp
2个回答
0
投票

您可以使用 Formidable

File
接口
filepath
属性将上传的文件内容读取到 Buffer 中。

...
import * as fs from 'fs';

...
const buf = await fs.promises.readFile(files.image.filepath);
await Sharp(buf);
...


...

0
投票

如果有人遇到这个问题,尝试将图像文件从客户端上传到服务器,并使用 Sharp 处理它们,我是这样做的:

在客户端,我发送带有表单数据的 POST 请求:

  const formData = new FormData()

  for (const file of files) {
    formData.append("files", file, file.name)
  }

  const r = await fetch(url, {
    method: "POST",
    body: formData,
  })

在服务器上,我们需要1)使用中间件(例如Express或单独的中间件文件 - 我使用后者)将多部分内容类型的表单数据处理为FileStream(它不会是文件对象),2)将FileStream处理为数据块,3)将数据块数组与缓冲区合并(参见this答案)并将它们附加到主体。我用过Busboy:

  const busboy = require('busboy')

  const parseMultipartBody = async (req, res, next) => {
    
    const bb = busboy({ headers: req.headers })

    req.body.filesAsBuffer = []

    // every file here will be FileStream, not File Object
    bb.on('file', (name, file, info) => {
    
      const data = []
      let fileAsBuffer
    
      file.on('data', (chunk) => {
        data.push(chunk)
      }).on('close', async () => {
        // merge data chunks with buffer and attach them to body
        fileAsBuffer = await Buffer.concat(data)
        req.body.filesAsBuffer.push(fileAsBuffer)
      })
    })

    bb.on('close', () => {
      next()
    })
  
    req.pipe(bb)
  }  

在路线上我们可以使用Sharp进行任何我们需要的操作:

  const sharp = require('sharp')

  export const POST = async (req, res) => {

    const { body } = req
    const { filesAsBuffer } = body

    for (const fileAsBuffer of filesAsBuffer) {
      const metadata = await sharp(fileAsBuffer).metadata()
      console.log(1, metadata)
    }
   
    ...
  }

© www.soinside.com 2019 - 2024. All rights reserved.