Upload de arquivo usando a solicitação POST no Node.js

Estou com problema ao fazer o upload do arquivo usando a solicitação POST no Node.js. Eu tenho que usar o módulo de request para realizar isso (sem npms externos). O servidor precisa que ele seja uma solicitação multipartes com o campo de arquivo contendo os dados do arquivo. O que parece ser fácil é muito difícil de fazer no Node.js sem usar nenhum módulo externo.

Eu tentei usar este exemplo, mas sem sucesso:

 request.post({ uri: url, method: 'POST', multipart: [{ body: '' }] }, function (err, resp, body) { if (err) { console.log('Error!'); } else { console.log('URL: ' + body); } }); 

   

Parece que você já está usando o módulo de request .

Nesse caso, tudo que você precisa para postar dados de multipart/form-data é usar seu recurso de form :

 var req = request.post(url, function (err, resp, body) { if (err) { console.log('Error!'); } else { console.log('URL: ' + body); } }); var form = req.form(); form.append('file', '', { filename: 'myfile.txt', contentType: 'text/plain' }); 

mas se você quiser publicar algum arquivo existente do seu sistema de arquivos, você pode simplesmente passá-lo como um stream legível:

 form.append('file', fs.createReadStream(filepath)); 

request irá extrair todos os metadados relacionados por si só.

Para obter mais informações sobre como postar dados de multipart/form-data consulte o módulo node-form-data , que é usado internamente por request .

Um recurso não documentado do campo formData que a request implementa é a capacidade de passar opções para o módulo de form-data ele usa:

 request({ url: 'http://example.com', method: 'POST', formData: { 'regularField': 'someValue', 'regularFile': someFileStream, 'customBufferFile': { value: fileBufferData, options: { filename: 'myfile.bin' } } } }, handleResponse); 

Isso é útil se você precisa evitar chamar requestObj.form() mas precisa carregar um buffer como um arquivo. O módulo de form-data também aceita opções contentType (o tipo MIME) e knownLength .

Esta alteração foi adicionada em outubro de 2014 (assim, dois meses após essa pergunta ser feita), portanto, deve ser seguro usar agora (em 2017+). Isso equivale à versão v2.46.0 ou acima da request .

A resposta de Leonid Beschastny funciona, mas eu também tive que converter ArrayBuffer para Buffer, que é usado no módulo request do Node. Depois de fazer o upload do arquivo para o servidor, eu o tive no mesmo formato que vem do arquivo HTML5 FileAPI (estou usando o Meteor). Código completo abaixo – talvez seja útil para os outros.

 function toBuffer(ab) { var buffer = new Buffer(ab.byteLength); var view = new Uint8Array(ab); for (var i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; } return buffer; } var req = request.post(url, function (err, resp, body) { if (err) { console.log('Error!'); } else { console.log('URL: ' + body); } }); var form = req.form(); form.append('file', toBuffer(file.data), { filename: file.name, contentType: file.type }); 

Você também pode usar o suporte a “opções personalizadas” da biblioteca de solicitações. Esse formato permite que você crie um upload de formulário com várias partes, mas com uma input combinada para as informações de arquivo e de formulário extra, como nome de arquivo ou tipo de conteúdo. Descobri que algumas bibliotecas esperam receber uploads de arquivos usando esse formato, especificamente bibliotecas como o multer.

Essa abordagem é oficialmente documentada na seção de formulários dos documentos de solicitação – https://github.com/request/request#forms

 //toUpload is the name of the input file:  let fileToUpload = req.file; let formData = { toUpload: { value: fs.createReadStream(path.join(__dirname, '..', '..','upload', fileToUpload.filename)), options: { filename: fileToUpload.originalname, contentType: fileToUpload.mimeType } } }; let options = { url: url, method: 'POST', formData: formData } request(options, function (err, resp, body) { if (err) cb(err); if (!err && resp.statusCode == 200) { cb(null, body); } });