Expressjs : issue with image file encoding during res.download

I have a pretty run-of-the-mill node.js server with expressjs installed locally for development purposes; I store various files and request them via a basic HTTP call that returns the file through express' res.download feature. Most of the time, this works without a hitch. For a very small subset of files, however, the end-user receives a file that is much larger than expected (almost 2x) and is unreadable by any conventional viewer. Out of maybe a hundred files, this has only happened twice, and both were JPG files, but the sample is too small to draw any conclusion. What I know :

  • The issue is reproductible : if it happens with a file, it always happens;
  • The issue is not related to the way files are stored : if I swap the problematic file with another one but keep everything else the same (name, location, etc.), it works fine;
  • Right before the res.download happens, the file is okay : checking its size with fs.stats returns the correct value
  • The HTTP response encounters no visible problem : no error, 200 response code...
  • The source file seems to have normal metadata and JPG markers

UPDATE I did some tests, and the issue seems to be somehow related to encoding : the mangled response file is, for reasons unknown, encoded in UTF-8 ; the size discrepancy comes from all non-UTF-8 characters being replaced by EF BF BD (the unknown character symbol) ! I still can't understand why it happens, what makes these few files different from others, and if it can be detected and/or corrected upstream.

UPDATE 2 After some additional tests, I still can't quite pinpoint the cause, but I can add the following info :

  • Systems-wise, the issue happens during the data streaming in fs.js

  • The root cause is located somewhere in the EXIF data of the image

For those interested, the source image (source.JPG) and download result (response.JPG) can be found here : http://www.sycomor.fr/test/ ; I also added a similar image that isn't affected by the download and comes out clean. For what it's worth, both pictures were taken minutes apart, with the same camera at the same settings, so I strongly doubt the issue is caused by some external source.

Thanks !

Your issue comes from 'connect-livereload' in your express configuration. It corrupts binary stream while injecting the reloading script.

Refer to https://github.com/intesso/connect-livereload/issues/39 for details.