NodeJS服务器端-文件预期的UploadFile,收到:〈类'字符串'>

5vf7fwbs  于 2022-11-22  发布在  Node.js
关注(0)|答案(2)|浏览(319)

从NodeJs服务器端上传文件有问题,发现100个帖子和研究,但没有工作,将感谢任何帮助。

应用程序的结构

  1. Front App - React Admin框架接收文件,并以base64编码图像内容以发送到API
    1.后端- NestJS应用程序-在API中接收base64映像
    1.从我的后端API需要发送文件到一个外部的后端(Python API)上传--问题就在这里
    请看下面我的代码,JS文件有问题
    我已经尝试了几种方法,所有这些方法都以相同的错误结束

1个解决方案

  • 将base64映像转换到缓冲区并发送到外部后端以上传文件
  • 我也尝试传递cleanImageBuffer,但没有任何更改
import axios from 'axios';
import FormData from 'form-data';

export async function upload(
  fileBase64: string,
  filename: string
): Promise<any> {

  const buffer = Buffer.from(fileBase64, 'base64')
  const extension = fileBase64.substring(fileBase64.indexOf('/') + 1, fileBase64.indexOf(";base64"))
  const cleanBase64 = fileBase64.replace(/^data:image\/png;base64,/, '')
  const cleanImageBuffer = Buffer.from(cleanBase64, 'base64')

  const formData = new FormData();
  // have tried to pass as well cleanImageBuffer but no changes
  formData.append('file', buffer);
  formData.append('fileName', filename + '.' + extension);
  formData.append('namespace', 'test');
  
  return await axios
    .post('external_api_url', JSON.stringify(formData), {
      headers: {
        Authorization: `Bearer token`,
        ContentType: 'multipart/form-data'
      }
    })
    .then((response) => {
      console.log('response = ' + JSON.stringify(response))
    })

结果1解决方案

{
    "status": "error",
    "error": {
        "code": "bad_request",
        "message": "file Expected UploadFile, received: <class 'str'>"
    }
}

2解决方案

  • 从收到的base64图像保存在我的磁盘上
  • 在创建流并发送图像之后
export async function upload (
  fileBase64: string,
  filename: string
): Promise<any> {

  const extension = fileBase64.substring(fileBase64.indexOf('/') + 1, fileBase64.indexOf(";base64"))
  const cleanBase64 = fileBase64.replace(/^data:image\/png;base64,/, '')

  const TMP_UPLOAD_PATH = '/tmp'

  if (!fs.existsSync(TMP_UPLOAD_PATH)) {
    fs.mkdirSync(TMP_UPLOAD_PATH);
  }

  fs.writeFile(TMP_UPLOAD_PATH + '/' + filename + '.' + extension, cleanBase64, 'base64', function(err) {
    console.log(err);
  })

  const fileStream = fs.createReadStream(TMP_UPLOAD_PATH + '/' + filename + '.' + extension)

  const formData = new FormData();
  formData.append('file', fileStream, filename + '.' + extension);
  formData.append('fileName', filename + '.' + extension);
  formData.append('namespace', 'test');

  return await axios
    .post('external_api_url', formData, {
      headers: {
        Authorization: `Bearer token`,
        ContentType: 'multipart/form-data'
      }
    })
    .then((response) => {
      console.log('response = ' + JSON.stringify(response))
    })
}

结果2解决方案

{
    "status": "error",
    "error": {
        "code": "bad_request",
        "message": "file Expected UploadFile, received: <class 'str'>"
    }
}

以相同结果结束其他解决方案

  • 尝试使用从节点提取-提取-相同结果
  • 发现有些人有一个过时的版本的axios和有这个问题,我已经安装了最新的axios版本1. 1. 3,但相同的结果

“我所需要的最佳方案"

  • 从收到的base64图像
  • 在缓冲区中转换并将文件发送到外部Python API,以避免将文件保存在本地磁盘上

我会很感激你的帮助

下面是一个python示例,它可以工作,但JS不工作(JS没有任何工作)

import requests

url = "http://127.0.0.1:8000/external_api"

payload={'namespace': 'test'}
files=[
  ('file',('lbl-pic.png',open('/local/path/lbl-pic.png','rb'),'image/png'))
]
headers = {
  'Authorization': 'Bearer token'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)
cqoc49vn

cqoc49vn1#

只是一个建议:

  • 这里有一行代码,它会返回上面提到的错误,你可能会发现它很有用。

1.首先看看是否可以使用常规HTML文件输入(还不要使用Base64),如这里所述https://stackoverflow.com/a/70824288/2347084
1.如果(1)有效,则尝试将base64转换为File对象,如下所示https://stackoverflow.com/a/47497249/2347084
1.合并(2)和(1)

rta7y2nd

rta7y2nd2#

我 想 发布 我 的 解决 方案 , 因为 我 可以 看到 在 互联 网 上 每个 人 都 有 问题 的 FormData 上 的 节点
1.我 正在 使用 axios 发送 上传 文件 的 缓冲 区

  1. axios 存在 一 个 问题 , 特别 是 FormData , 它 没有 在 头 文件 中 添加 Content-Lenght , 任何 版本 的 axios 都 不会 这样 做
  2. python API 需要 内容 长度
    因此 , 我们 很 友好 地 要求 在 python API 中 选择 性 地 使用 这个 头 , 代码 开始 工作 了
    解决 办法 是 如果 有人 遇到 类似 的 问题
  • axios 在 使用 FormData 时 不 添加 Content-Lenght ( 找 不到 任何 可用 的 axios 版本 )
  • 如果 您 使用 缓冲 区 , 而 本地 磁盘 上 没有 该 文件 , 则 会 由于 Content-Lenght 而 出现 问题
  • 如果 你 在 本地 有 文件 , 而 不是 使用 模块 fs , 你 就 能够 读取 文件 , 并 添加 所有 的 标题 和 内容 长度

关于 axios 的 GitHub 问题 , 我 说 这个 bug 在 最 新 的 axios 中 已经 修复 了 , 但是 在 我 的 例子 中 它 仍然 不 起 作用
下面 是 使用 缓冲 区 的 代码 , 第 三 个 API 中 不 需要 内容 长度

function upload (image: {imageBase64: string, fileName: string}) {
  const { imageBase64, fileName } = image;
  const cleanBase64 = imageBase64.substr(imageBase64.indexOf(',') + 1);
  // buffer should be clean base64
  const buffer = Buffer.from(cleanBase64, 'base64');

  const formData = new FormData();
  // filename as option is required, otherwise will not work, will say that received file is string and UploadFile
  formData.append('file', buffer, { filename: fileName });

  return client
    .post('url', formData, {
      headers: {
        ...formData.getHeaders(),
      },
    })
    .then((response) => response.data)
    .catch((error) => {
      return {
        status: 'error',
        error,
      };
    });
}

中 的 每 一 个

相关问题