From 45294d31cbf8d447861b09ce62e6bd5f9362b975 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Sun, 25 Jan 2026 12:34:35 +0100 Subject: [PATCH] In Node.js, don't abort the full request for local PDF files smaller than two range requests This follows the behaviour used with both the Fetch API and `XMLHttpRequest`, compare with the `validateRangeRequestCapabilities` helper function. --- src/display/node_stream.js | 8 +++++++- test/unit/node_stream_spec.js | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/display/node_stream.js b/src/display/node_stream.js index 36f1b1a8d..e42a1b9e9 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -104,8 +104,14 @@ class PDFNodeStreamFsFullReader { const fs = process.getBuiltinModule("fs"); fs.promises.lstat(this._url).then( stat => { + const { size } = stat; + if (size <= 2 * this._rangeChunkSize) { + // The file size is smaller than the size of two chunks, so it doesn't + // make any sense to abort the request and retry with a range request. + this._isRangeSupported = false; + } // Setting right content length. - this._contentLength = stat.size; + this._contentLength = size; this._setReadableStream(fs.createReadStream(this._url)); this._headersCapability.resolve(); diff --git a/test/unit/node_stream_spec.js b/test/unit/node_stream_spec.js index cab12391b..9da1aaa93 100644 --- a/test/unit/node_stream_spec.js +++ b/test/unit/node_stream_spec.js @@ -117,4 +117,41 @@ describe("node_stream", function () { expect(isRangeSupported).toEqual(true); expect(fullReaderCancelled).toEqual(true); }); + + it("read filesystem pdf files (smaller than two range requests)", async function () { + const smallPdf = new URL("./test/pdfs/empty.pdf", cwdURL).href; + const smallLength = 4920; + + const stream = new PDFNodeStream({ + url: smallPdf, + rangeChunkSize: 65536, + disableStream: true, + disableRange: false, + }); + + const fullReader = stream.getFullReader(); + + let isStreamingSupported, isRangeSupported; + const promise = fullReader.headersReady.then(() => { + isStreamingSupported = fullReader.isStreamingSupported; + isRangeSupported = fullReader.isRangeSupported; + }); + + let len = 0; + const read = function () { + return fullReader.read().then(function (result) { + if (result.done) { + return undefined; + } + len += result.value.byteLength; + return read(); + }); + }; + + await Promise.all([read(), promise]); + + expect(isStreamingSupported).toEqual(false); + expect(isRangeSupported).toEqual(false); + expect(len).toEqual(smallLength); + }); });