title: hashing a streaming file before uploading to S3
body: <p>I am trying to stream a file to S3 without storing the file to disk/ssd. I would like to have part of the hash of the file as a part of the filename when uploading to S3.</p>
  <p>EDIT_v1:<br />
  Been trying to follow this post using <code>busboy</code> as the parser: <a href="https://stackoverflow.com/questions/30840819/calculate-a-file-hash-and-save-the-file">Calculate a file hash and save the file</a>. I took an example from the busboy docs and adabpted it with an answer from the post:</p>
  <pre class="lang-js prettyprint-override"><code>const server = http.createServer();
  server.on('request', async (req, res) =&gt; {
    if (req.method === 'POST') {
      const bb = busboy({ headers: req.headers });
  
      bb.on('file', (name, file, info) =&gt; {
        const { filename, encoding, mimeType } = info;
        console.log(
          `File [${name}]: filename: %j, encoding: %j, mimeType: %j`,
          filename,
          encoding,
          mimeType
        );
  
        const fileHashSource = new PassThrough();
        const writeSource = new PassThrough();
        file.pipe(fileHashSource);
        file.pipe(writeSource);
  
        fileHashSource.resume();
        writeSource.resume();
  
        createFileHash(fileHashSource, (err, hash) =&gt; {
          if (err) {
            console.log('err', err)
            return res.end('some err');
          }
  
          const writeStream = fs.createWriteStream(`test_${hash.slice(0, 8)}.png`);
          writeStream.on('error', function(err) {
            console.log('write error', err);
            return res.end('write error')
          });
          writeStream.on('finish', function() {
            console.log('write finished')
            return res.end('done')
          });
  
          writeSource.pipe(writeStream);
        });
      });
      bb.on('field', (name, val, info) =&gt; {
        console.log(`Field [${name}]: value: %j`, val);
      });
      bb.on('close', () =&gt; {
        console.log('Done parsing form!');
        req.unpipe(bb);
        res.writeHead(201, { Connection: 'close' });
        res.end('done!');
      });
  
      req.pipe(bb);
    } else if (req.method === 'GET') {
      res.writeHead(200, { Connection: 'close' });
      res.end(`
        &lt;body style=&quot;background-color: black&quot;&gt;
          &lt;form enctype=&quot;multipart/form-data&quot; method=&quot;post&quot;&gt;
            &lt;label&gt;file name
              &lt;input type=&quot;text&quot; name=&quot;textfield&quot; /&gt;
            &lt;/label&gt;&lt;br /&gt;
            &lt;label&gt;single file
              &lt;input type=&quot;file&quot; name=&quot;filefield&quot; /&gt;
            &lt;/label&gt;&lt;br /&gt;
  
            &lt;br /&gt;
            &lt;button type=&quot;submit&quot;&gt;Upload&lt;/button&gt;
          &lt;/form&gt;
        &lt;/body&gt;
      `);
    }
  })
  
  server.listen(3000, () =&gt; {
    console.info(`NodeJS process: ${process.pid}`)
    console.info(`Listening on port: 3000`)
  });
  
  
  function createFileHash(readStream, next) {
    const hash = crypto.createHash('sha1');
    hash.setEncoding('hex');
  
    hash.on('error', function(err) {
      console.log('hash error')
      return next(err);
    });
    hash.on('finish', function(data) {
      console.log('hash finished');
      return next(null, hash.read());
    });
  
    readStream.pipe(hash);
  }
  </code></pre>
  <p>EDIT_v2:<br />
  see first answer below for a solution</p>