mozilla/pdf.js — pull request #3634 by nmaier (2013-09-01 15:00:21+00:00)
Title: Firefox: Corrupt downloads ("padded" downloads) when there is no content length

When the server does not provide a Content-Length with the initial PDF request, e.g. when chunked transfer-encoding is used - which is common for dynamically generated files, then the Download action of pdf.js will not save the data as retrieved, but instead the data will be padded by 0-bytes up to a certain bound.

What happens is the following:
* PdfDataListener will get an initial buffer of 0x10000 (64kb) length when the size is unknown. https://github.com/mozilla/pdf.js/blob/8a4a6f498f06a86e27336d71dc08f06ecb78d3cd/extensions/firefox/components/PdfStreamConverter.js#L139
* When that buffer would overflow during the data transfer, it is doubled again and again until the data would fit. (BTW: This seems a bit wasteful once you get into the multi-MB area...) https://github.com/mozilla/pdf.js/blob/8a4a6f498f06a86e27336d71dc08f06ecb78d3cd/extensions/firefox/components/PdfStreamConverter.js#L149-L157
* However, when the data transfer completes, neither is the buffer shrunk to the actual size again, nor is the actual size noted -> On download the full, over-sized buffer will be saved. Only a new `.subarray()` view is taken: https://github.com/mozilla/pdf.js/blob/8a4a6f498f06a86e27336d71dc08f06ecb78d3cd/extensions/firefox/components/PdfStreamConverter.js#L165
* The blobURI created for the download will use the underlying buffer, which is still over-sized: https://github.com/mozilla/pdf.js/blob/427dd3948be41f68daf2e3e3ad9bbeab94b920e3/web/viewer.js#L630

STR:
* Open http://alpha.papeeria.com/d/pdf/f6cbdf88778f3bfc2217fc3745373cc5.pdf which uses chunked transfer-encoding (provided by @gkalabin via http://stackoverflow.com/q/18538195/484441)
* Hit the pdf.js download button and save the pdf.

Expected:
File size should be 5420 byte.

Actual:
File size is 65536 byte (0x10000, initial buffer size) and the file is padded by 0-bytes after the initial transfer.

cc @yurydelendik