0

Please have a look at the following sample code.

As you can see, it uses busboy to parse incoming form data and write incoming files to disc. Let's assume these are just image files because my sample code makes use of imgur.com. (a content-length header doesn't need to be sent) The imgurUpload() function makes use of node-form-data

Is it somehow possible to stream the image files additionally, without the need to buffer them complete, to imgur.com? (to the imgurUpload() function and use it within node-form-data?)

Server / listener:

var http = require('http'),
  Busboy = require('busboy'),
  FormData = require('form-data'),
  fs = require('fs')

http.createServer(function(req, res) {
  if (req.method === 'POST') {
    var busboy = new Busboy({
      headers: req.headers
    })
    busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
      //pipe the stream to disc
      file.pipe(fs.createWriteStream('1st-' + filename))
      //pipe the stream a 2nd time
      file.pipe(fs.createWriteStream('2nd-' + filename))

      /* how to connect things together? */
    })
    busboy.on('finish', function() {
      res.writeHead(200, {
        'Connection': 'close'
      })
      res.end("upload complete")
    })
    return req.pipe(busboy)
  } else if (req.method === 'GET') {
    var stream = fs.createReadStream(__dirname + '/index.html')
    stream.pipe(res)
  }
}).listen(80, function() {
  console.log('listening for requests')
})

HTML test form (index.html)

<!doctype html>
<head></head>
<body>
  <form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="submit">
  </form>
</body>
</html>

Sample function that submits an image file to imgur.com:

function imgurUpload(stream) {

  var form = new FormData()
  //form.append('Filedata', fs.createReadStream('test.jpg'))

  form.append('Filedata', /* how to connect things together? */X )
  form.submit('http://imgur.com/upload', function(err, res) {
    if (err) throw err

    var body = ''
    res.on('data', function(chunk) { body += chunk })
    res.on('end', function() { console.log('http://imgur.com/' + JSON.parse(body).data.hash) })
  })
}

Update (regarding mscdex answer)

_stream_readable.js:748
    throw new Error('Cannot switch to old mode now.');
          ^
Error: Cannot switch to old mode now.
    at emitDataEvents (_stream_readable.js:748:11)
    at FileStream.Readable.pause (_stream_readable.js:739:3)
    at Function.DelayedStream.create (\path\node_modules\form-data\node_modules\combined-stream\node_modules\delayed-stream\lib\delayed_stream.js:35:12)
    at FormData.CombinedStream.append (\path\node_modules\form-data\node_modules\combined-stream\lib\combined_stream.js:45:30)
    at FormData.append (\path\node_modules\form-data\lib\form_data.js:43:3)
    at imgurUpload (\path\app.js:54:8)
    at Busboy.<anonymous> (\path\app.js:21:4)
    at Busboy.emit (events.js:106:17)
    at Busboy.emit (\path\node_modules\busboy\lib\main.js:31:35)
    at PartStream.<anonymous> (\path\node_modules\busboy\lib\types\multipart.js:205:13)
jaspis
  • 1
  • 1

1 Answers1

1

You can append Readable streams as shown in node-form-data's readme. So this:

form.append('Filedata', stream);

should work just fine.

Then in your file event handler:

imgurUpload(file);
mscdex
  • 104,356
  • 15
  • 192
  • 153
  • I already tried it this way but ran into an error (updated my question and added the error log). I did not note the "Cannot switch to old mode now" before. I looked it up and found this post: [link](https://stackoverflow.com/a/20181116/4121003) - so it should work, but it isn't because a module is still using the old stream interface which is causing problems? – jaspis Oct 08 '14 at 20:33
  • Sounds like a bug in the `form-data` and/or `combined-stream` modules. – mscdex Oct 08 '14 at 21:42