Search code examples
node.jsrequestmultergridfs-stream

POST file using request, gridfs-stream and multer


In my node.js-application, I need to read data from a MongoDB with GridFS and upload it to another server via POST request, I am using the modules gridfs-stream, request and multer.
According to the request docs I can simply add a stream for multipart/form-data, so I'm doing this:

var fileUuid = "myFilename";

var options = {
    url: "url.to/my/target/",
    method: "POST",
    header: {"Content-Type": "multipart/form-data"},
    formData: {
        filedata: gfs.createReadStream({filename: fileUuid})
    }
}

request(options, function(error, response, body) {
    if (error) {
        console.log("[" + getDateTime() + "] Error replicating file:");
        console.log(error);
        return;
    }

    console.log('statusCode: ', response && response.statusCode); 
    console.log('body: ', body);
});

On my receiving server, I have the following code:

var upload = multer({ dest: './tmp_upload/' })

app.post('/my/target', upload.single('filedata'), function(req, res) {
    console.log('['+getDateTime()+'] Request received');
}

But whenever I am executing the request, I get the following error on my sending server:

[2019:07:26:16:52:00] Error replicating file:
Error: write ECONNRESET

and this on my receiving server:

Error: Unexpected end of multipart data
    at c:\Users\...\node_modules\dicer\lib\Dicer.js:62:28
    at process._tickCallback (internal/process/next_tick.js:61:11)

Can anybody please give me a hint how to POST my file from one server to another?

EDIT:
The issue seems to be the gfs.createReadStream({filename: fileUuid}) type of stream... When I write the file to the filesystem first and instead put an fs.createReadStream(...) into the form as formData, then it works.
But is there an option to direct the stream directly into the formData, without having to write it to disk first?


Solution

  • So I ended up working with a temporary file that I read from the database, write it to disk and create a new readStream that I then put into the request. After the request was successful, I delete the temporary file from my disk and continue with my code:

    var fsstreamwrite = fs.createWriteStream("./tmp/" + myFile);
    var readstream = gfs.createReadStream( {filename: myFile} );
    readstream.pipe(fsstreamwrite);
    readstream.on("close", function () {
        console.log("File read successfully from database");
    
        var options = {
            url: "url.to/my/target/",
            method: "POST",
            enctype: "multipart/form-data",
            formData: {
                "filedata": fs.createReadStream('./tmp/' + myFile)
            }
        }
    
        request(options, function(error, response, body) {
            if (error) {
                // error handling
                return;
            }
    
            // delete temporary file
            fs.unlinkSync('./tmp/' + myFile)
    
            // continue with my stuff...
    
        });                                    
    
    });