mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
Content disposition filename
File name is extracted from headers.
This commit is contained in:
parent
96c573ad38
commit
eb1f6f4c24
8 changed files with 139 additions and 21 deletions
|
@ -2001,8 +2001,10 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||
return {
|
||||
info: results[0],
|
||||
metadata: (results[1] ? new Metadata(results[1]) : null),
|
||||
contentDispositionFileName: (this._fullReader ?
|
||||
this._fullReader.fileName : null),
|
||||
};
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getStats: function WorkerTransport_getStats() {
|
||||
|
|
|
@ -17,8 +17,8 @@ import {
|
|||
AbortException, assert, createPromiseCapability
|
||||
} from '../shared/util';
|
||||
import {
|
||||
createResponseStatusError, validateRangeRequestCapabilities,
|
||||
validateResponseStatus
|
||||
createResponseStatusError, extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities, validateResponseStatus
|
||||
} from './network_utils';
|
||||
|
||||
function createFetchOptions(headers, withCredentials) {
|
||||
|
@ -67,6 +67,7 @@ class PDFFetchStream {
|
|||
class PDFFetchStreamReader {
|
||||
constructor(stream) {
|
||||
this._stream = stream;
|
||||
this._fileName = null;
|
||||
this._reader = null;
|
||||
this._loaded = 0;
|
||||
let source = stream.source;
|
||||
|
@ -100,11 +101,13 @@ class PDFFetchStreamReader {
|
|||
this._reader = response.body.getReader();
|
||||
this._headersCapability.resolve();
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
return response.headers.get(name);
|
||||
};
|
||||
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader: (name) => {
|
||||
return response.headers.get(name);
|
||||
},
|
||||
getResponseHeader,
|
||||
isHttp: this._stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
|
@ -112,6 +115,7 @@ class PDFFetchStreamReader {
|
|||
|
||||
this._contentLength = suggestedLength;
|
||||
this._isRangeSupported = allowRangeRequests;
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
|
||||
// We need to stop reading when range is supported and streaming is
|
||||
// disabled.
|
||||
|
@ -131,6 +135,10 @@ class PDFFetchStreamReader {
|
|||
return this._contentLength;
|
||||
}
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
}
|
||||
|
||||
get isRangeSupported() {
|
||||
return this._isRangeSupported;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
|
||||
import { assert, createPromiseCapability, stringToBytes } from '../shared/util';
|
||||
import {
|
||||
createResponseStatusError, validateRangeRequestCapabilities
|
||||
createResponseStatusError, extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities
|
||||
} from './network_utils';
|
||||
import globalScope from '../shared/global_scope';
|
||||
|
||||
|
@ -340,6 +341,7 @@ function PDFNetworkStreamFullRequestReader(manager, source) {
|
|||
this._requests = [];
|
||||
this._done = false;
|
||||
this._storedError = undefined;
|
||||
this._fileName = null;
|
||||
|
||||
this.onProgress = null;
|
||||
}
|
||||
|
@ -350,11 +352,13 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
var fullRequestXhrId = this._fullRequestId;
|
||||
var fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
return fullRequestXhr.getResponseHeader(name);
|
||||
};
|
||||
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader: (name) => {
|
||||
return fullRequestXhr.getResponseHeader(name);
|
||||
},
|
||||
getResponseHeader,
|
||||
isHttp: this._manager.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
|
@ -381,6 +385,11 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
networkManager.abortRequest(fullRequestXhrId);
|
||||
}
|
||||
|
||||
// Content-Disposition: attachment; filename=Naïve file.txt
|
||||
if (networkManager.isPendingRequest(fullRequestXhrId)) {
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
}
|
||||
|
||||
this._headersReceivedCapability.resolve();
|
||||
},
|
||||
|
||||
|
@ -429,6 +438,10 @@ PDFNetworkStreamFullRequestReader.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
},
|
||||
|
||||
get isRangeSupported() {
|
||||
return this._isRangeSupported;
|
||||
},
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
import {
|
||||
assert, MissingPDFException, UnexpectedResponseException
|
||||
} from '../shared/util';
|
||||
import { getFilenameFromUrl } from './dom_utils';
|
||||
|
||||
function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
||||
rangeChunkSize, disableRange, }) {
|
||||
|
@ -65,8 +66,23 @@ 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,
|
||||
validateRangeRequestCapabilities,
|
||||
validateResponseStatus,
|
||||
extractFilenameFromHeader,
|
||||
};
|
||||
|
|
|
@ -22,7 +22,9 @@ let url = __non_webpack_require__('url');
|
|||
import {
|
||||
AbortException, assert, createPromiseCapability
|
||||
} from '../shared/util';
|
||||
import { validateRangeRequestCapabilities } from './network_utils';
|
||||
import {
|
||||
extractFilenameFromHeader, validateRangeRequestCapabilities
|
||||
} from './network_utils';
|
||||
|
||||
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
||||
|
||||
|
@ -74,6 +76,7 @@ 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
|
||||
|
@ -109,6 +112,10 @@ class BaseFullReader {
|
|||
return this._isStreamingSupported;
|
||||
}
|
||||
|
||||
get fileName() {
|
||||
return this._fileName;
|
||||
}
|
||||
|
||||
read() {
|
||||
return this._readCapability.promise.then(() => {
|
||||
if (this._done) {
|
||||
|
@ -284,13 +291,15 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
this._headersCapability.resolve();
|
||||
this._setReadableStream(response);
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
// Make sure that headers name are in lower case, as mentioned
|
||||
// here: https://nodejs.org/api/http.html#http_message_headers.
|
||||
return this._readableStream.headers[name.toLowerCase()];
|
||||
};
|
||||
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader: (name) => {
|
||||
// Make sure that headers name are in lower case, as mentioned
|
||||
// here: https://nodejs.org/api/http.html#http_message_headers.
|
||||
return this._readableStream.headers[name.toLowerCase()];
|
||||
},
|
||||
getResponseHeader,
|
||||
isHttp: stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
|
@ -301,6 +310,9 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
}
|
||||
// Setting right content length.
|
||||
this._contentLength = suggestedLength;
|
||||
|
||||
// Setting the file name from the response header
|
||||
this._fileName = extractFilenameFromHeader(getResponseHeader);
|
||||
};
|
||||
|
||||
this._request = null;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue