J'ai des problèmes pour télécharger le fichier avec la demande POST dans Node.js. Je dois utiliser le module request
pour accomplir cela (pas de npms externe). Le serveur doit en faire une demande en plusieurs parties avec le champ file
contenant les données du fichier. Ce qui semble être facile est assez difficile à faire dans Node.js sans utiliser de module externe.
J'ai essayé d'utiliser cet exemple mais sans succès:
request.post({
uri: url,
method: 'POST',
multipart: [{
body: '<FILE_DATA>'
}]
}, function (err, resp, body) {
if (err) {
console.log('Error!');
} else {
console.log('URL: ' + body);
}
});
On dirait que vous utilisez déjà module request
.
dans ce cas, tout ce dont vous avez besoin de poster multipart/form-data
consiste à utiliser sa form
feature :
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', '<FILE_DATA>', {
filename: 'myfile.txt',
contentType: 'text/plain'
});
mais si vous souhaitez publier un fichier existant à partir de votre système de fichiers, vous pouvez simplement le transmettre sous forme de flux lisible:
form.append('file', fs.createReadStream(filepath));
request
extraira toutes les métadonnées associées par lui-même.
Pour plus d'informations sur la publication de multipart/form-data
voir module node-form-data
, utilisé en interne par request
.
Une fonctionnalité non documentée du champ formData
que request
implémente est la possibilité de passer des options au module form-data
qu'il utilise:
request({
url: 'http://example.com',
method: 'POST',
formData: {
'regularField': 'someValue',
'regularFile': someFileStream,
'customBufferFile': {
value: fileBufferData,
options: {
filename: 'myfile.bin'
}
}
}
}, handleResponse);
Ceci est utile si vous devez éviter d'appeler requestObj.form()
mais devez télécharger un tampon sous forme de fichier. Le module form-data
accepte également les options contentType
(type MIME) et knownLength
.
Ce changement a été ajouté en octobre 2014 (donc 2 mois après que cette question a été posée), il devrait donc être utilisé sans danger maintenant (en 2017+). Cela équivaut à la version v2.46.0
ou supérieure de request
.
La réponse de Leonid Beschastny fonctionne, mais j'ai également dû convertir ArrayBuffer en Buffer utilisé dans le module request
du nœud. Après avoir téléchargé le fichier sur le serveur, je l'avais dans le même format que celui de FileAPI HTML5 (j'utilise Meteor). Le code complet ci-dessous - peut-être sera-t-il utile pour les autres.
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
});
Vous pouvez également utiliser le support "options personnalisées" de la bibliothèque de demandes. Ce format vous permet de créer un téléchargement de formulaire en plusieurs parties, mais avec une entrée combinée pour le fichier et les informations de formulaire supplémentaires, telles que le nom de fichier ou le type de contenu. J'ai constaté que certaines bibliothèques s'attendent à recevoir des téléchargements de fichiers utilisant ce format, en particulier des bibliothèques telles que multer.
Cette approche est officiellement documentée dans la section formulaires de la documentation de la demande - https://github.com/request/request#forms
//toUpload is the name of the input file: <input type="file" name="toUpload">
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);
}
});