1
\$\begingroup\$

I'm implementing a file upload using NodeJS. I've got fully functional code, however, it feels overly complicated and I'm hoping there would be an easier way to implement the same thing?

In particular what I want to achieve is:

  • Write the request to a file
  • Send upload progress information
  • Send final MD5 hash
  • Send final size (position)
  • Properly propagate errors
  • Have no resource leaks

app.post('/file', (req, res, next) => {

  // ...

  const progress$ = Observable
    .create(o => {
      const fileStream = fs.createWriteStream(filePath, { flags: 'wx' })
      const hasher = crypto.createHash('md5')

      req.on('data', buf => {
        hasher.update(buf)
        o.next({
          position: fileStream.bytesWritten
        })
        if (!fileStream.write(buf)) {
          req.pause()
        }
      })
      req.on('error', err => {
        fileStream.destroy()
        o.error(err)
      })
      req.on('end', ::fileStream.end)
      req.on('close', () => {
        fileStream.destroy()
        o.error(new Error('upload cancelled'))
      })
      fileStream.on('drain', ::req.resume)
      fileStream.on('error', ::o.error)
      fileStream.on('close', () => {
        o.next({
          md5: hasher.digest('hex'),
          position: fileStream.bytesWritten
        })
        o.complete()
      })
    })

 // ...

})
\$\endgroup\$
  • 1
    \$\begingroup\$ Note to reviewers: OP is using the experimental function bind syntax (::function). You'll need this babel plugin to run his code. \$\endgroup\$ – Dan Pantry Jul 9 '16 at 17:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.