Reputation: 533
I've read on request's documentation page that one can stream a file to a PUT or POST request, like this:
fs.createReadStream('file.json').pipe(request.put('http://example.com/obj.json'));
request.get('http://google.com/img.png').pipe(request.put('http://example.com/img.png'));
But it seems to be not working. I've tried to set up a local server for uploading files using different libraries.
express-busboy:
var express = require('express');
var app = express();
var fs = require('fs');
var bb = require('express-busboy');
var app = express();
bb.extend(app, {
upload: true,
path: './img/',
allowedPath: /./
});
app.post('/upload', function(req, res) {
console.log(req.files);
});
var server = app.listen(process.env.PORT, function() {
console.log('Listening on port %d', server.address().port);
});
and formidable:
var express = require('express');
var app = express();
var path = require('path');
var fs = require('fs');
var formidable = require('formidable');
app.post('/upload', function(req, res){
// create an incoming form object
var form = new formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/img');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
fs.rename(file.path, path.join(form.uploadDir, file.name));
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.end('success');
});
// parse the incoming request containing the form data
form.parse(req);
});
var server = app.listen(process.env.PORT, function() {
console.log('Listening on port %d', server.address().port);
});
Both work fine when I'm making request like this:
var request = require('request');
var fs = require('fs');
var formData = {
filename: {
value: fs.createReadStream('ice.jpg'),
options: {
filename: 'ice.jpg',
contentType: ' image/jpeg'
}}
};
request.post({url: 'https://myserver.com/upload', formData: formData});
Or from the command line:
curl -i -X POST -H "Content-Type: multipart/form-data" -F "[email protected]" https://myserver.com/upload
But none of them work when I'm trying to do this:
fs.createReadStream('ice.jpg').pipe(request.post('https://myserver.com/upload'));
Am I doing something wrong? Is there a way to make the last line to work?
Upvotes: 3
Views: 6988
Reputation: 533
OK. I'm answering the question in case someone will have the similar problem.
Curl and request.post with formData option both send post requests with a "Content-Type: multipart/form-data" header. Libraries like express-busboy, formidable, and multer are used to parse that data.
This line:
fs.createReadStream('ice.jpg').pipe(request.post('https://myserver.com/upload'));
send a request with "Content-Type: image/jpeg" and "Transfer-Encoding: chunked" headers. No need to parse multipart form data here.
The following code on the server will work in this type of scenario:
var http = require('http');
var fs = require('fs');
var server = http.createServer(function(req, res){
console.log(req.headers);
var body = [];
req
.on('data', chunk => {
body.push(chunk);
console.log('Chunk ', chunk);
})
.on('end', () => {
body = Buffer.concat(body);
fs.writeFileSync('newfile.jpg', body, null);
});
res.write("OK\n");
res.end();
});
Upvotes: 4