Re-factor the blob-URL caching in DownloadManager.openOrDownloadData

Cache blob-URLs on the actual data, rather than DOM elements, to reduce potential duplicates (note the updated unit-test).
This commit is contained in:
Jonas Jenwald 2023-10-16 16:20:46 +02:00
parent 22d6d95f03
commit 674052d3fc
7 changed files with 17 additions and 18 deletions

View File

@ -806,7 +806,6 @@ class LinkAnnotationElement extends AnnotationElement {
link.href = this.linkService.getAnchorUrl(""); link.href = this.linkService.getAnchorUrl("");
link.onclick = () => { link.onclick = () => {
this.downloadManager?.openOrDownloadData( this.downloadManager?.openOrDownloadData(
this.container,
attachment.content, attachment.content,
attachment.filename, attachment.filename,
dest dest
@ -2861,11 +2860,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
* Download the file attachment associated with this annotation. * Download the file attachment associated with this annotation.
*/ */
#download() { #download() {
this.downloadManager?.openOrDownloadData( this.downloadManager?.openOrDownloadData(this.content, this.filename);
this.container,
this.content,
this.filename
);
} }
} }

View File

@ -2883,6 +2883,11 @@ describe("api", function () {
expect(attachmentDest).toEqual('[0,{"name":"Fit"}]'); expect(attachmentDest).toEqual('[0,{"name":"Fit"}]');
// Check that the attachments, which are identical, aren't duplicated.
for (let i = 1, ii = annotations.length; i < ii; i++) {
expect(annotations[i].attachment).toBe(attachment);
}
await loadingTask.destroy(); await loadingTask.destroy();
}); });

View File

@ -67,7 +67,7 @@ class DownloadManager {
/** /**
* @returns {boolean} Indicating if the data was opened. * @returns {boolean} Indicating if the data was opened.
*/ */
openOrDownloadData(element, data, filename, dest = null) { openOrDownloadData(data, filename, dest = null) {
const isPdfData = isPdfFile(filename); const isPdfData = isPdfFile(filename);
const contentType = isPdfData ? "application/pdf" : ""; const contentType = isPdfData ? "application/pdf" : "";
@ -75,10 +75,10 @@ class DownloadManager {
(typeof PDFJSDev === "undefined" || !PDFJSDev.test("COMPONENTS")) && (typeof PDFJSDev === "undefined" || !PDFJSDev.test("COMPONENTS")) &&
isPdfData isPdfData
) { ) {
let blobUrl = this.#openBlobUrls.get(element); let blobUrl = this.#openBlobUrls.get(data);
if (!blobUrl) { if (!blobUrl) {
blobUrl = URL.createObjectURL(new Blob([data], { type: contentType })); blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
this.#openBlobUrls.set(element, blobUrl); this.#openBlobUrls.set(data, blobUrl);
} }
let viewerUrl; let viewerUrl;
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
@ -105,7 +105,7 @@ class DownloadManager {
// Release the `blobUrl`, since opening it failed, and fallback to // Release the `blobUrl`, since opening it failed, and fallback to
// downloading the PDF file. // downloading the PDF file.
URL.revokeObjectURL(blobUrl); URL.revokeObjectURL(blobUrl);
this.#openBlobUrls.delete(element); this.#openBlobUrls.delete(data);
} }
} }

View File

@ -132,15 +132,15 @@ class DownloadManager {
/** /**
* @returns {boolean} Indicating if the data was opened. * @returns {boolean} Indicating if the data was opened.
*/ */
openOrDownloadData(element, data, filename, dest = null) { openOrDownloadData(data, filename, dest = null) {
const isPdfData = isPdfFile(filename); const isPdfData = isPdfFile(filename);
const contentType = isPdfData ? "application/pdf" : ""; const contentType = isPdfData ? "application/pdf" : "";
if (isPdfData) { if (isPdfData) {
let blobUrl = this.#openBlobUrls.get(element); let blobUrl = this.#openBlobUrls.get(data);
if (!blobUrl) { if (!blobUrl) {
blobUrl = URL.createObjectURL(new Blob([data], { type: contentType })); blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
this.#openBlobUrls.set(element, blobUrl); this.#openBlobUrls.set(data, blobUrl);
} }
// Let Firefox's content handler catch the URL and display the PDF. // Let Firefox's content handler catch the URL and display the PDF.
let viewerUrl = blobUrl + "?filename=" + encodeURIComponent(filename); let viewerUrl = blobUrl + "?filename=" + encodeURIComponent(filename);
@ -156,7 +156,7 @@ class DownloadManager {
// Release the `blobUrl`, since opening it failed, and fallback to // Release the `blobUrl`, since opening it failed, and fallback to
// downloading the PDF file. // downloading the PDF file.
URL.revokeObjectURL(blobUrl); URL.revokeObjectURL(blobUrl);
this.#openBlobUrls.delete(element); this.#openBlobUrls.delete(data);
} }
} }

View File

@ -158,12 +158,12 @@ class IDownloadManager {
downloadData(data, filename, contentType) {} downloadData(data, filename, contentType) {}
/** /**
* @param {HTMLElement} element
* @param {Uint8Array} data * @param {Uint8Array} data
* @param {string} filename * @param {string} filename
* @param {string | null} [dest]
* @returns {boolean} Indicating if the data was opened. * @returns {boolean} Indicating if the data was opened.
*/ */
openOrDownloadData(element, data, filename) {} openOrDownloadData(data, filename, dest = null) {}
/** /**
* @param {Blob} blob * @param {Blob} blob

View File

@ -91,7 +91,7 @@ class PDFAttachmentViewer extends BaseTreeViewer {
*/ */
_bindLink(element, { content, filename }) { _bindLink(element, { content, filename }) {
element.onclick = () => { element.onclick = () => {
this.downloadManager.openOrDownloadData(element, content, filename); this.downloadManager.openOrDownloadData(content, filename);
return false; return false;
}; };
} }

View File

@ -133,7 +133,6 @@ class PDFOutlineViewer extends BaseTreeViewer {
element.href = linkService.getAnchorUrl(""); element.href = linkService.getAnchorUrl("");
element.onclick = () => { element.onclick = () => {
this.downloadManager.openOrDownloadData( this.downloadManager.openOrDownloadData(
element,
attachment.content, attachment.content,
attachment.filename attachment.filename
); );