处理节点文件对象 - 将文件上传到 Amazon S3 抛出 [ERR_INVALID_ARG_TYPE]

问题描述

我有一个非常简单的设置,使用:Axios > Express > S3 (v3:@aws-sdk/client-s3)。

文件到达 Node 端时,它会自动转换为 Node File Object 格式(我不知道如何处理)。 @aws-sdk 尝试将其转换为缓冲区,这会引发 buffer.js:333 中的错误

抛出的完整错误(减去调用堆栈)是:

TypeError [ERR_INVALID_ARG_TYPE]:第一个 参数必须是字符串类型或 Buffer、ArrayBuffer、 或数组或类似数组的对象。收到一个文件实例

这是脚本的相关部分。

// Frontend.js
const sendImage = () => {
  const image = document.querySelector('#photoupload');
  const formData = new FormData();
  formData.append('image',image.files[0]);
  axios.post('http://192.168.1.152:3200/addImage',formData,{
    headers: {
      'content-type': 'multipart/form-data',},});
};
// express-server.js
app.use(cors());
app.use(formidable())
app.post('/addImage',(req,res) => {
  const file = req.files;
  uploadOnetoBucket('my_s3_bucket',file);
});
// s3_uploadMethod.js
const uploadOnetoBucket = (bucketName,file) => {
  const params = {
    Bucket: bucketName,ACL: 'public-read',Body: file.image,Key: file.image.name,};
  const s3Upload = s3.send(new PutObjectCommand(params));
  // handle Promises
};

我不太确定如何解决这个问题。一个问题,我应该如何处理节点文件对象,以便 S3 PutObjectCommand 可以使用它? 另一个问题是,文件上传的最佳实践是什么,我见过人们谈论转换为 base64 缓冲区,而其他人则说要流式传输。 感谢你们的帮助!

解决方法

一种解决方案是将前端的文件转换为 base64,将其放入 FormData 对象中,然后在服务器端将其转换回。这种方法的缺点是 base64 字符串比原始文件大 30% 左右。我认为那里有更好的解决方案。

修改后的代码使用了内置的 FileReader Object

 // Frontend.js 
 const sendImage = () => {
    const image = document.querySelector('#photoupload').files[0];
    const reader = new FileReader();
    const formData = new FormData();
    reader.addEventListener('loadend',() => {
      formData.append('image',image.name + reader.result);
      axios.post('http://192.168.1.152:3200/addImage',formData,{
        headers: {
          'content-type': 'multipart/form-data',},});
    });
    reader.readAsDataURL(image);
  };
// server.js
app.use(cors());
app.use(formidable());
app.post('/addImage',(req,res) => {
  const file = req.fields;
  uploadOneToBucket('my_s3_bucket',file.image);
});
// s3_uploadMethod.js
const uploadOneToBucket = (bucketName,file) => {
  const data = file.split(',');
  const decodedBuffer = Buffer.from(data[1],'base64');
  const filename = (data[0].split('data')[0]);

  const params = {
    Bucket: bucketName,ACL: 'public-read',Body: decodedBuffer,Key: filename,};
  // ...

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...