Node.js 在没有多部分中间件的情况下正确解析node/express中的FormData文件?

Node.js 在没有多部分中间件的情况下正确解析node/express中的FormData文件?,node.js,forms,express,fetch,buffer,Node.js,Forms,Express,Fetch,Buffer,我试图正确解析http.IncomingMessage对象,并试图找出处理从FormData对象接收的不同文件的最佳使用实践。我的目标是不使用表单解析中间件,如multer/fornighous/busboy等,尽管通过查看它们的源代码,我已经得到了足够的提示,可以让它工作到目前为止 这是我的密码: 后端: router.post('/upload', (req, res) => { const webkitRegexp = new RegExp('--WebKit');

我试图正确解析http.IncomingMessage对象,并试图找出处理从FormData对象接收的不同文件的最佳使用实践。我的目标是不使用表单解析中间件,如multer/fornighous/busboy等,尽管通过查看它们的源代码,我已经得到了足够的提示,可以让它工作到目前为止

这是我的密码:

后端

router.post('/upload', (req, res) => {
    const webkitRegexp = new RegExp('--WebKit');
    let i = 0;
    let body = [];
    req.on('data', chunk => {
        body.push(chunk);
        let headerFilter = body[i].toString();
        if (webkitRegexp.test(headerFilter)) console.log(`i: ${i}, t/f: ${webkitRegexp.test(headerFilter)}`);
        i++;
    })
    .on('end', () => {
        let file = Buffer.concat(body);
        fs.appendFile('./test1.pdf', file, "utf8");
    })
})


module.exports = router;
(HTML):
<div id="upload"></div>
        <form method="POST" action="/api/upload">
            <input type="file" name="fileInput" id="fileInput">
            <button id="fileSubmitButton" type="submit">Upload</button>
        </form>


(JS):
fileSubmitButton.addEventListener("click", event => {
    event.preventDefault();
    const formData = new FormData();
    formData.append('file', fileInput.files[0]);

    const options = {
        method: 'POST',
        body: formData
    }
    fetch('/api/upload', options);
});
前端

router.post('/upload', (req, res) => {
    const webkitRegexp = new RegExp('--WebKit');
    let i = 0;
    let body = [];
    req.on('data', chunk => {
        body.push(chunk);
        let headerFilter = body[i].toString();
        if (webkitRegexp.test(headerFilter)) console.log(`i: ${i}, t/f: ${webkitRegexp.test(headerFilter)}`);
        i++;
    })
    .on('end', () => {
        let file = Buffer.concat(body);
        fs.appendFile('./test1.pdf', file, "utf8");
    })
})


module.exports = router;
(HTML):
<div id="upload"></div>
        <form method="POST" action="/api/upload">
            <input type="file" name="fileInput" id="fileInput">
            <button id="fileSubmitButton" type="submit">Upload</button>
        </form>


(JS):
fileSubmitButton.addEventListener("click", event => {
    event.preventDefault();
    const formData = new FormData();
    formData.append('file', fileInput.files[0]);

    const options = {
        method: 'POST',
        body: formData
    }
    fetch('/api/upload', options);
});
(HTML):
上传
(JS):
fileSubmitButton.addEventListener(“单击”,事件=>{
event.preventDefault();
const formData=new formData();
formData.append('file',fileInput.files[0]);
常量选项={
方法:“POST”,
正文:formData
}
获取('/api/upload',选项);
});
到目前为止,当我使用上述代码上传一个文件(例如PDF文件)时,它是有效的。这很粗糙,但很有效。然而,我确信我做得不是很“干净”或正确。首先,文件大小随着每次传输而增加,因为表单头附着在文件的顶部:

------WebKitFormBoundaryIHdsrd2LUJ3swA55
Content-Disposition: form-data; name="file"; filename="test2.pdf"
Content-Type: application/pdf

------WebKitFormBoundaryKBIGn3csB55i68XN
Content-Disposition: form-data; name="file"; filename="vzw_coi_agreement.pdf"
Content-Type: application/pdf

%PDF-1.4
%����
43 0 obj
<</Linearized 1/L 417824/O 45/E 38624/N 14/T 416844/H [ 416 170]>>
endobj
               
xref
43 6
0000000016 00000 n
0000000586 00000 n
0000000649 00000 n
0000000838 00000 n
0000000947 00000 n
0000000416 00000 n
trailer
<</Size 49/Root 44 0 R/Info 42 0 R/ID[<C7F3B3EAC78D2F720E9C16C3F3E1E7FE><775B5807B229A245A8B09FE97F2C5522>]/Prev 416833>>
startxref
0
%%EOF
             
48 0 obj
<</Filter/FlateDecode/I 121/Length 90/S 90>>stream
h�b```f``��
----WebKitFormBoundaryIHdsrd2LUJ3swA55
内容配置:表单数据;name=“file”;filename=“test2.pdf”
内容类型:application/pdf
------WebKitFormBoundaryKBIGn3csB55i68XN
内容配置:表单数据;name=“file”;filename=“vzw_coi_agreement.pdf”
内容类型:application/pdf
%PDF-1.4
%����
43 0 obj
endobj
外部参照
43 6
00000001600000N
000000058600000 n
000000064900000N
0000000838000000N
0000000 947 00000n
00000004160百万元
拖车
起始外部参照
0
%%EOF
48 0 obj
流动
H�b``f``��
正如您在我的代码中所看到的,我试图向下钻取包含标头的确切区块,因此无法将其推入正文[],但是,每个区块都包含标头以及PDF文件的许多开始数据。是否已经有一种方法可以只解析表单中的文件,并从区块数据中过滤出标题?我是否需要使用request.on('data')方法以外的其他流读取器方法?也许可以请求。管道(身体)能给我提供更好的路线吗?我的一个想法是,不仅要将每个块转换为字符串并运行test(),还要迭代每个块本身,直到找到我想要的字符串并跳过将其推入body[]的过程。也许有人可以帮我编写代码,或者我可以避免这种情况,还有一种更好的技术

再说一次,我知道我可以引进multer或Fergous,然后就完蛋了。然而,我对学习这些包是如何工作的很感兴趣,通过自己做类似的事情,它可以帮助我学习node/JS/express。我发现了一些类似的问题,但通常有人会回答“使用multer”,就是这样。我发现使用这种原始文件和数据技术非常有趣,如果您能帮助我编写一些关于如何优雅地处理这个问题的优秀代码,我将不胜感激

如果你需要任何其他信息,请告诉我。多谢各位


Jordan

正如您所知,您的导出文件会随着每个请求而增长,因为
fs.appendFile
将数据附加到它,而不是重写它。此外,如果您直接使用
req.on('data')
处理数据,则可以分别解析边界、标题和内容:-)@ΔO'deltazero::澄清一下,文件在一次传输后会从原始文件大小增长。例如,如果原始文件大小为5000B,则传输的文件为5200B。我不再对同一个文件调用appendFile()。这是因为您的第二点,头被添加到原始数据块中。当我将数据块视为一个整体时,如何分别解析边界、标题和内容?您必须解析MIME标题,以便只获得所需的内容。而且,您可能还必须正确解码内容。而且,如果你最终拥有多个部分的身体,那就更难了。如果您真的要研究所有相关规范,并且能够处理发送给您的任何内容,那么完整的MIME解析器需要大量的工作。通过研究发送的内容,您可能会发现如何使一种特定类型的响应起作用,但是任何一种通用的MIME解析器都需要大量的工作才能找出所有的bug。您可能会发现,创建一个列表,列出进行适当的MIME解析所需的所有RFC是非常有用的。如果你真的找到了所有这些,这会让你大致知道这需要花费多少时间才能做好。好的,谢谢大家的帮助。