Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pipe a uploaded file to a remote server with node (ideally with same filename)

I want to upload a file in my app.js server , which should pipe that file to a crossdomain server like my upload.js server.

The full code can be found under the following link

The upload.js server is working. My problem is the app.js server. Request seems to be capable of streaming files (https://github.com/request/request#streaming). But I dont get it working. I am always getting : [Error: Invalid protocol] in my app.js.

It musst be this line:

fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))

I changed post to put and in my upload.js the post method also to put, but it results in the same error.

My Goal is to upload a file from the html page to localhost:3000/upload which pipes the file to localhost:4000/upload (ideally with same filename) . But I dont get it working (this post doesn't helped me).

app.js:

var express = require('express')
    , multiparty = require('multiparty')
    , request = require('request')
    , fs = require('fs')
    , util = require('util')
    , http = require('http');

var app = express();
app.use('/static', express.static('static'));

process.on('uncaughtException', function (err) {
    console.log(err);
});

app.get('/', function (req, res) {
    res.redirect('static/index.html');
});

app.post('/upload', function(req, res, next){

    //https://github.com/request/request#streaming

    var form = new multiparty.Form();

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        res.end(util.inspect({fields: fields, files: files}));
    });
    form.on('file', function(name,file) {

        //stream it to localhost:4000 with same name
        fs.createReadStream(file.path).pipe(request.post('localhost:4000/upload'))

        console.log(file.path);
    });

});

var server = app.listen(3000, '0.0.0.0' ,function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('Example app listening at http://%s:%s', host, port);
});

index.html:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Upload</title>
</head>
<body>
  <h2>Upload</h2>
  <form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" id="file" name="file" />
    <button>upload</button>
  </form>
</body>
</html>

upload.js:

var express = require('express')
    , multiparty = require('multiparty')
    , cors = require('cors')
    , util = require('util')
    , app = express();

app.use(cors());
process.on('uncaughtException', function (err) {
    console.log(err);
});

app.get('/', cors(), function(req, res, next){
    res.json({msg: 'This is CORS-enabled for all origins!'});
});

app.post('/upload', cors(), function(req, res, next){
    var form = new multiparty.Form();

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        res.end(util.inspect({fields: fields, files: files}));
    });
    form.on('file', function(name,file) {
        console.log(file);
        console.log(name);
    });

});

app.listen(4000, function(){
    console.log('CORS-enabled web server listening on port 4000');
});
like image 986
svenhornberg Avatar asked Aug 21 '15 11:08

svenhornberg


People also ask

What is __ filename in node?

The __filename represents the filename of the code being executed. This is the resolved absolute path of this code file. For a main program, this is not necessarily the same filename used in the command line. The value inside a module is the path to that module file.

Which module is used for file upload in node JS?

Uploading File Using Multer in Nodejs: Multer is the most popular module for uploading files. You can upload files of any kind. Multer can be used to upload single or multiple files. It attaches the files in the request body object for uploading the files into the server.


1 Answers

Updated

I believe you're missing the protocol from the url. It should work, if you add the http protocol to the url:

fs.createReadStream(file.path).pipe(request.post('http://localhost:4000/upload'))

Make Upload work

When you pipe the file contents to the POST function in upload.js, the multipart form data is lost. You need to create a new POST request and pass the original file contents.

Do the following in app.js:

 form.on('file', function(name, file) {

    var formData = {
      file: {
        value:  fs.createReadStream(file.path),
        options: {
          filename: file.originalFilename
        }
      }
    };

    // Post the file to the upload server
    request.post({url: 'http://localhost:4000/upload', formData: formData});
}

This will also pass the original filename. For more information see: https://github.com/request/request#multipartform-data-multipart-form-uploads

like image 115
kmandov Avatar answered Nov 15 '22 19:11

kmandov