在 NodeJS 中解析使用 Axios 执行的多部分/混合响应的最佳方法是什么?

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

已经好几天了,我一直被困在一个我认为应该解决的简单问题上......

我有一个 NodeJS Express 应用程序,根据对特定路由的请求,它会向外部服务发出带有有效负载的 AXIOS post 请求。 该服务确实以多部分/混合内容类型进行响应(标题中提到了内容类型)。 响应包含一个 PDF 和一个包含信息的 JSON。

我成功地将response.data完全保存为PDF格式在AWS S3上。 但我无法找到至少一种方法来解析response.data以提取我需要的JSON信息。

这是我在邮递员回复面板中得到的内容, (正如您所注意到的,这是一种在 Colissimo 上生成法国邮政服务标签的方法)

我还可以补充一点,我尝试了很多 npm 包,但没有成功。

非常感谢,如果您知道如何操作它!

--uuid:f0bf15c8-03ba-41a4-8c9a-aac9d8e0d9ca
Content-Type: application/json;charset=UTF-8
Content-Transfer-Encoding: binary
Content-ID: <jsonInfos>

{"messages":[{"id":"0","type":"INFOS","messageContent":"La requête a été traitée avec succès","replacementValues":[]}],"labelXmlV2Reponse":null,"labelV2Response":{"parcelNumber":"8R42943164203","parcelNumberPartner":null,"pdfUrl":null,"fields":null}}
--uuid:f0bf15c8-03ba-41a4-8c9a-aac9d8e0d9ca
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <label>

%PDF-1.4
%����
3 0 obj <</Filter/FlateDecode/Length 1567>>stream
x��X�n7��W�L��;�`��)��!��I)�@��Ts�����������]

.... and more

我的路线中的简单 AXIOS 请求

let url = "https://ws.colissimo.fr/sls-ws/SlsServiceWSRest/2.0/generateLabel";

const response = await axios({
        url,
        method: 'POST',
        data,
        responseType: "stream"
      });
      console.log("data", response.data);
node.js express axios multipart
2个回答
1
投票

我在向 Colissimo 网络服务请求标签时遇到了同样的问题。 下面是我在测试时发现的解决方案:

function streamToString (stream) {
    const chunks = [];
    return new Promise((resolve, reject) => {
        stream.on('data', (chunk) => chunks.push(Buffer.from(chunk)));
        stream.on('error', (err) => reject(err));
        stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
    })
}

axios.post(urlApiRest, generateLabelData, {responseType: 'stream'}).then(res => {
    res.data.pipe(fs.createWriteStream('../public/test.pdf')); // write label to pdf
    streamToString(res.data).then(strData => {
        const jsonInfo = extractInfoFromColissimoResponse(res, strData);
        console.log(jsonInfo.labelV2Response.parcelNumber); // retrieve parcel number
    });
}).catch(err => {
    console.log(err);
});

function extractInfoFromColissimoResponse(res, data) {
    let header = res.headers['content-type'];
    let boundary = header.split(' ')[1];
    boundary = boundary.split('=')[1];
    boundary = boundary.split('"')[1];
    
    const infoPart = data.split('--' + boundary)[1];
    const txtInfo = infoPart.split('<jsonInfos>')[1];

    return JSON.parse(txtInfo);
}

0
投票

我知道这是一个老问题,但我在使用相同的 API 时发现了它,并且我认为我的方法更加安全。

您可以使用nodemailer包中的简单解析器。您只需从响应中获取所有标头即可。例如:

const axios = require('axios');
const simpleParser = require('mailparser').simpleParser;

const {headers, data} = await axios.post(url, requestBody, { responseType: 'arraybuffer' });

const rawHeaders = Object.entries(result.headers)
    .map(([key, value]) => `${key}: ${value}`)
    .join('\r\n');

const content = Buffer.concat([Buffer.from(rawHeaders + '\r\n', 'ascii'), data]);
const parsed = await simpleParser(content);
const infoAttachment = parsed.attachments.find(
    (attachment) => attachment.cid === 'jsonInfos',
);
const infos = JSON.parse(infoAttachment.content.toString());

const labelAttachment = parsed.attachments.find(
    (attachment) => attachment.cid === 'label',
);
© www.soinside.com 2019 - 2024. All rights reserved.