mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
Address the final round of review comments for Content-Disposition filename extraction
This patch updates the `IPDFStreamReader` interface and ensures that the interface/implementation of `network.js`, `fetch_stream.js`, `node_stream.js`, and `transport_stream.js` all match properly. The unit-tests are also adjusted, to more closely replicate the actual behaviour of the various actual `IPDFStreamReader` implementations. Finally, this patch adjusts the use of the Content-Disposition filename when setting the title in the viewer, and adds `PDFDocumentProperties` support as well.
This commit is contained in:
parent
eb1f6f4c24
commit
69a8336cf1
12 changed files with 151 additions and 121 deletions
|
@ -103,6 +103,16 @@ IPDFStreamReader.prototype = {
|
|||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the Content-Disposition filename. It is defined after the headersReady
|
||||
* promise is resolved.
|
||||
* @returns {string|null} The filename, or `null` if the Content-Disposition
|
||||
* header is missing/invalid.
|
||||
*/
|
||||
get filename() {
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets PDF binary data length. It is defined after the headersReady promise
|
||||
* is resolved.
|
||||
|
|
|
@ -1997,14 +1997,14 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
|
||||
getMetadata: function WorkerTransport_getMetadata() {
|
||||
return this.messageHandler.sendWithPromise('GetMetadata', null).
|
||||
then(function transportMetadata(results) {
|
||||
then((results) => {
|
||||
return {
|
||||
info: results[0],
|
||||
metadata: (results[1] ? new Metadata(results[1]) : null),
|
||||
contentDispositionFileName: (this._fullReader ?
|
||||
this._fullReader.fileName : null),
|
||||
contentDispositionFilename: (this._fullReader ?
|
||||
this._fullReader.filename : null),
|
||||
};
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
getStats: function WorkerTransport_getStats() {
|
||||
|
|
|
@ -67,9 +67,9 @@ class PDFFetchStream {
|
|||
class PDFFetchStreamReader {
|
||||
constructor(stream) {
|
||||
this._stream = stream;
|
||||
this._fileName = null;
|
||||
this._reader = null;
|
||||
this._loaded = 0;
|
||||
this._filename = null;
|
||||
let source = stream.source;
|
||||
this._withCredentials = source.withCredentials;
|
||||
this._contentLength = source.length;
|
||||
|
@ -104,7 +104,6 @@ class PDFFetchStreamReader {
|
|||
const getResponseHeader = (name) => {
|
||||
return response.headers.get(name);
|
||||
};
|
||||
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
|
@ -115,7 +114,8 @@ class PDFFetchStreamReader {
|
|||
|
||||
this._contentLength = suggestedLength;
|
||||
this._isRangeSupported = allowRangeRequests;
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
|
||||
this._filename = extractFilenameFromHeader(getResponseHeader);
|
||||
|
||||
// We need to stop reading when range is supported and streaming is
|
||||
// disabled.
|
||||
|
@ -131,12 +131,12 @@ class PDFFetchStreamReader {
|
|||
return this._headersCapability.promise;
|
||||
}
|
||||
|
||||
get contentLength() {
|
||||
return this._contentLength;
|
||||
get filename() {
|
||||
return this._filename;
|
||||
}
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
get contentLength() {
|
||||
return this._contentLength;
|
||||
}
|
||||
|
||||
get isRangeSupported() {
|
||||
|
|
|
@ -341,7 +341,7 @@ function PDFNetworkStreamFullRequestReader(manager, source) {
|
|||
this._requests = [];
|
||||
this._done = false;
|
||||
this._storedError = undefined;
|
||||
this._fileName = null;
|
||||
this._filename = null;
|
||||
|
||||
this.onProgress = null;
|
||||
}
|
||||
|
@ -371,6 +371,8 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
this._isRangeSupported = true;
|
||||
}
|
||||
|
||||
this._filename = extractFilenameFromHeader(getResponseHeader);
|
||||
|
||||
var networkManager = this._manager;
|
||||
if (networkManager.isStreamingRequest(fullRequestXhrId)) {
|
||||
// We can continue fetching when progressive loading is enabled,
|
||||
|
@ -385,11 +387,6 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
networkManager.abortRequest(fullRequestXhrId);
|
||||
}
|
||||
|
||||
// Content-Disposition: attachment; filename=Naïve file.txt
|
||||
if (networkManager.isPendingRequest(fullRequestXhrId)) {
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
}
|
||||
|
||||
this._headersReceivedCapability.resolve();
|
||||
},
|
||||
|
||||
|
@ -438,8 +435,8 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
get filename() {
|
||||
return this._filename;
|
||||
},
|
||||
|
||||
get isRangeSupported() {
|
||||
|
|
|
@ -53,6 +53,18 @@ function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
|||
return returnValues;
|
||||
}
|
||||
|
||||
function extractFilenameFromHeader(getResponseHeader) {
|
||||
const contentDisposition = getResponseHeader('Content-Disposition');
|
||||
if (contentDisposition) {
|
||||
let parts =
|
||||
/.+;\s*filename=(?:'|")(.+\.pdf)(?:'|")/gi.exec(contentDisposition);
|
||||
if (parts !== null && parts.length > 1) {
|
||||
return getFilenameFromUrl(parts[1]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function createResponseStatusError(status, url) {
|
||||
if (status === 404 || status === 0 && /^file:/.test(url)) {
|
||||
return new MissingPDFException('Missing PDF "' + url + '".');
|
||||
|
@ -66,23 +78,9 @@ function validateResponseStatus(status) {
|
|||
return status === 200 || status === 206;
|
||||
}
|
||||
|
||||
function extractFilenameFromHeader(getResponseHeader) {
|
||||
const contentDisposition = getResponseHeader('Content-Disposition');
|
||||
|
||||
if (contentDisposition) {
|
||||
let parts =
|
||||
/.+;\s*filename=(?:"|')(.+\.pdf)(?:"|')/gi.exec(contentDisposition);
|
||||
if (parts !== null && parts.length > 1) {
|
||||
return getFilenameFromUrl(parts[1]);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export {
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
validateResponseStatus,
|
||||
extractFilenameFromHeader,
|
||||
};
|
||||
|
|
|
@ -76,11 +76,11 @@ class BaseFullReader {
|
|||
this._done = false;
|
||||
this._errored = false;
|
||||
this._reason = null;
|
||||
this._fileName = null;
|
||||
this.onProgress = null;
|
||||
let source = stream.source;
|
||||
this._contentLength = source.length; // optional
|
||||
this._loaded = 0;
|
||||
this._filename = null;
|
||||
|
||||
this._disableRange = source.disableRange || false;
|
||||
this._rangeChunkSize = source.rangeChunkSize;
|
||||
|
@ -100,6 +100,10 @@ class BaseFullReader {
|
|||
return this._headersCapability.promise;
|
||||
}
|
||||
|
||||
get filename() {
|
||||
return this._filename;
|
||||
}
|
||||
|
||||
get contentLength() {
|
||||
return this._contentLength;
|
||||
}
|
||||
|
@ -112,10 +116,6 @@ class BaseFullReader {
|
|||
return this._isStreamingSupported;
|
||||
}
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
}
|
||||
|
||||
read() {
|
||||
return this._readCapability.promise.then(() => {
|
||||
if (this._done) {
|
||||
|
@ -296,14 +296,13 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
// here: https://nodejs.org/api/http.html#http_message_headers.
|
||||
return this._readableStream.headers[name.toLowerCase()];
|
||||
};
|
||||
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
});
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
});
|
||||
|
||||
if (allowRangeRequests) {
|
||||
this._isRangeSupported = true;
|
||||
|
@ -311,8 +310,7 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
// Setting right content length.
|
||||
this._contentLength = suggestedLength;
|
||||
|
||||
// Setting the file name from the response header
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
this._filename = extractFilenameFromHeader(getResponseHeader);
|
||||
};
|
||||
|
||||
this._request = null;
|
||||
|
|
|
@ -119,6 +119,7 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
|
|||
function PDFDataTransportStreamReader(stream, queuedChunks) {
|
||||
this._stream = stream;
|
||||
this._done = false;
|
||||
this._filename = null;
|
||||
this._queuedChunks = queuedChunks || [];
|
||||
this._requests = [];
|
||||
this._headersReady = Promise.resolve();
|
||||
|
@ -143,6 +144,10 @@ var PDFDataTransportStream = (function PDFDataTransportStreamClosure() {
|
|||
return this._headersReady;
|
||||
},
|
||||
|
||||
get filename() {
|
||||
return this._filename;
|
||||
},
|
||||
|
||||
get isRangeSupported() {
|
||||
return this._stream._isRangeSupported;
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue