【问题标题】:Parse images inside a JSON in HTTP request在 HTTP 请求中解析 JSON 中的图像
【发布时间】:2021-08-03 19:47:39
【问题描述】:

我在我的 React 应用程序中发送了一个请求,其中包含一个带有各种字段的 JSON 正文,其中有一个 File 类型图像的数组。

const body = {
  title: 'title',
  price: 100,
  images: [...]
};

axios.post(url, body);

这不起作用,images 数组到达 Express 应用程序时为空。 我咨询了互联网并尝试使用FormData。但是,我看到的所有解决方案(example)都只有图像,即

const images = [...];
const data = new FormData();
images.forEach(img => data.append(img.title, img));

但我想要整个东西——文本和图像,因为这个输入应该进入 MongoDB。 我试过简单地将整个对象放在FormData

const data = new FormData();
data.append('body', body);

但我一定不明白 FormData 的实际工作原理,因为在 Express 中尝试 iterate overreq.body 只会产生任何结果:

app.get((req, res) => {
  const data = Object.fromEntries(req.body) // yields nothing
}

使用multer 之类的任何其他尝试都强化了我做错了什么,因为我一生都无法获得非空的请求正文。

我想做的是能够发送完整的 HTTP 数据主体,其中包括文本、数字和图像数组,这样我就可以在 Express 应用程序上将这些图像保存到磁盘。 任何好的建议将不胜感激。

【问题讨论】:

  • 只是给出一个想法(它可能不是最好的)我最近遇到了类似的问题(我正在使用 nodejs azure 函数来上传图像并且不希望它变得太复杂)我通过像这样images: ['base64string','base64string'] 将原始base64 作为字符串传递给服务器来解决它
  • @ShmiliBreuer 其余的 JSON 只是 JSON?还是将整个东西翻译成base64?
  • 其余的是常规 JSON(图像也是纯 json,不涉及 FormData),我不能说这是否是一种正确/有效的方法,它只是最简单最划算的在那个特定的低优先级用例上为我提供了一种方式。
  • 我可能遗漏了一些东西。您使用Buffer.from(img).toString('base64') 将文件转换为字符串,我想您是如何将它们在服务器上转换为可行文件的?
  • 在我的情况下,我在我的快递服务器上将它上传到一个名为 imagekit 的图像托管服务,他们接受一个 base64 字符串来上传图像(所以我不需要将它转换为文件) ,但在您的情况下,将其保存到磁盘也许stackoverflow.com/a/6933413/3161811 可以提供帮助。

标签: node.js reactjs express xmlhttprequest


【解决方案1】:

您不能使用 json 来发送图像(不是原始文件),但是有一个带有表单数据的选项。 首先,您必须将文件与普通数据分开,并将普通数据解析为字符串。

const images = [...];
const body = new FormData();
// you have to put the images in the same field, and the server will recibe an array
images.forEach(img => body.append('images', img));
// the other data to send
const data = {
  someData: true,
  moreData: 1,
arrOfNormalData: [23,10];
}
const parsedData = JSON.stringify(data);
body.append('_jsonData', parsedData);
axios.post(url, body);

您在请求的_jsonData 字段中将json 数据作为字符串发送。 然后在你的节点服务器上,你必须在配置它 ej 上安装 multer

const path = require('path');
//this is for a ramdom id for file name
const { nanoid } = require('nanoid');
const multer = require('multer');

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads')
  },
  filename: function (req, file, cb) {
    cb(null, nanoid() + path.extname(file.originalname));
  }
})
 
const upload = multer({ storage: storage });

然后你可以创建一个中间件来将数据(记住我们将它转​​换为字符串)解析为一个对象。

const parseJson = (field = '_jsonData') => {
    return (req, res, next) => {
        if (req.body[field] && typeof req.body[field] === 'string') {
            req.body = JSON.parse(req.body[field]);
        }
        next();
    };
};

然后让我们在我们的路由中使用

app.get(upload.array('images',10),parseJson(),(req, res) => {
  const data = req.body;// here the json data
const files = req.files;// here the uploaded files
}

我们添加了upload.array('images',10),其中images 是文件字段,10 是最大文件数 我们添加了我们的 parseJons 中间件来将stirng解析为json 希望它对您有所帮助,并且不要使用base64,如果您使用base64,您可能会遇到问题。使用表单数据 附言。对不起,我的英语不太好。

【讨论】:

  • 我已经尝试实现你的方法,但是我的服务器在upload.array()parseJson() 之间的某个地方崩溃了。我用日志跟踪请求,它达到了存储功能,但没有达到解析,实际上没有文件被写入磁盘,所以我对那里可能发生的事情感到非常困惑。你对此有什么想法吗?
  • 请您分享日志错误,并尝试const upload = multer({dest: 'uploads/'}),并尝试使用post 方法而不是get
  • 我确实尝试过post,但这无关紧要。这些错误与 Jade 有关,我不知道:express:view require "jade"express:view lookup "error.jade" 然后是statrender 关于error.jade。在此之前,我看到路由到一些匿名函数,我假设这些是中间件。 dest: 'uploads/'storage 的补充还是替代?
  • @RonnyEfronny 使用const upload = multer({dest: 'uploads/'}) 而不是storage,如果您看到“jade”可能是您的观点有问题,请用您的观点验证您的快速设置
猜你喜欢
  • 2011-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
相关资源
最近更新 更多