diff --git a/src/Document.jsx b/src/Document.jsx
index 7b78da7e5..59a0b1f07 100644
--- a/src/Document.jsx
+++ b/src/Document.jsx
@@ -85,8 +85,11 @@ export default class Document extends PureComponent {
// If rendering is in progress, let's cancel it
cancelRunningTask(this.runningTask);
- // If loading is in progress, let's destroy it
+ // If pdfjs loading is in progress, let's destroy it
if (this.loadingTask) this.loadingTask.destroy();
+
+ // If FileReader loading is in progress, let's abort it
+ if (this.loadFromFileTask) this.loadFromFileTask.cancel();
}
loadDocument = () => {
@@ -263,7 +266,14 @@ export default class Document extends PureComponent {
if (isBrowser) {
// File is a Blob
if (isBlob(file) || isFile(file)) {
- loadFromFile(file).then((data) => {
+ // abort previous FileReader, if there is one
+ if (this.loadFromFileTask) {
+ this.loadFromFileTask.cancel();
+ }
+
+ this.loadFromFileTask = loadFromFile(file);
+ this.loadFromFileTask.promise.then((data) => {
+ this.loadFromFileTask = null;
resolve({ data });
});
return;
diff --git a/src/Page.jsx b/src/Page.jsx
index 371655b72..40d53480b 100644
--- a/src/Page.jsx
+++ b/src/Page.jsx
@@ -246,6 +246,13 @@ export class PageInternal extends PureComponent {
return { page: null };
});
+ // eslint-disable-next-line no-underscore-dangle
+ if (pdf && pdf._transport && pdf._transport.destroyed) {
+ this.setState({ page: false });
+ this.onLoadError(new Error('Attempted to load a page, but the document was destroyed'));
+ return;
+ }
+
const cancellable = makeCancellable(pdf.getPage(pageNumber));
this.runningTask = cancellable;
diff --git a/src/shared/utils.js b/src/shared/utils.js
index e6e38fd4f..9c4403cb6 100644
--- a/src/shared/utils.js
+++ b/src/shared/utils.js
@@ -141,9 +141,8 @@ export function isCancelException(error) {
}
export function loadFromFile(file) {
- return new Promise((resolve, reject) => {
- const reader = new FileReader();
-
+ const reader = new FileReader();
+ const promise = new Promise((resolve, reject) => {
reader.onload = () => resolve(new Uint8Array(reader.result));
reader.onerror = (event) => {
switch (event.target.error.code) {
@@ -163,4 +162,11 @@ export function loadFromFile(file) {
return null;
});
+
+ return {
+ promise,
+ cancel: () => {
+ reader.abort();
+ },
+ };
}
diff --git a/test/LoadingOptions.jsx b/test/LoadingOptions.jsx
index d77ae240c..ba37e58ff 100644
--- a/test/LoadingOptions.jsx
+++ b/test/LoadingOptions.jsx
@@ -8,6 +8,8 @@ import { isFile } from './shared/propTypes';
export default function LoadingOptions({
file,
setFile,
+ useExternPage,
+ setUseExternPage,
setRender,
}) {
function onFileChange(event) {
@@ -122,6 +124,18 @@ export default function LoadingOptions({
Unload file
+
+
+ { setUseExternPage(event.target.checked); }}
+ />
+
+
);
}
@@ -130,4 +144,6 @@ LoadingOptions.propTypes = {
file: isFile,
setFile: PropTypes.func.isRequired,
setRender: PropTypes.func.isRequired,
+ setUseExternPage: PropTypes.func.isRequired,
+ useExternPage: PropTypes.bool.isRequired,
};
diff --git a/test/Test.jsx b/test/Test.jsx
index ccdfb7dee..6ca992c15 100644
--- a/test/Test.jsx
+++ b/test/Test.jsx
@@ -12,6 +12,8 @@ import {
loadFromFile,
} from 'react-pdf/src/shared/utils';
+import { isFile as propTypeIsFile } from './shared/propTypes';
+
import './Test.less';
import AnnotationOptions from './AnnotationOptions';
@@ -54,6 +56,7 @@ export const readAsDataURL = (file) => new Promise((resolve, reject) => {
export default function Test() {
const [displayAll, setDisplayAll] = useState(false);
+ const [useExternPage, setUseExternPage] = useState(false);
const [externalLinkTarget, setExternalLinkTarget] = useState(null);
const [file, setFile] = useState(null);
const [fileForProps, setFileForProps] = useState(null);
@@ -146,7 +149,7 @@ export default function Test() {
if (isBrowser) {
// File is a Blob
if (isBlob(file) || isFile(file)) {
- return { data: await loadFromFile(file) };
+ return { data: await loadFromFile(file).promise };
}
}
return file;
@@ -219,6 +222,8 @@ export default function Test() {
- console.log('Clicked a document', { event, pdf })}
@@ -319,9 +325,107 @@ export default function Test() {
)}
+ {/* eslint-disable-next-line */}
+ // eslint-disable-next-line indent
+ : }
);
}
+
+// test element outside of element
+const TestSeparateDocumentAndPage = function (props) {
+ const { file } = props;
+ const [display, setDisplay] = useState(true);
+ const [displayPage, setDisplayPage] = useState(true);
+ const [document, setDocument] = useState(null);
+ const [numPages, setNumPages] = useState(0);
+ const [pageNumber, setPageNumber] = useState(1);
+ const [unountOnFile, setUnountOnFile] = useState(false);
+
+ // unmount Document as soon as file starts loading
+ useEffect(() => {
+ if (file && unountOnFile) {
+ setDisplay(false);
+ }
+ }, [file]);
+
+ const onDocumentLoadSuccess = (pdf) => {
+ console.log('Loaded a document', pdf);
+ if (pdf && pdf.numPages) {
+ setNumPages(pdf.numPages);
+ }
+ setDocument(pdf);
+ };
+
+ const onPageLoadSuccess = (page) => {
+ console.log('Loaded a page', page);
+ };
+
+ const onPageLoadError = (error) => {
+ console.log('error loading a page:', error);
+ };
+
+ const toggleDocument = () => {
+ setDisplay(!display);
+ };
+
+ const pageNumberDec = () => {
+ if (pageNumber > 1) {
+ setPageNumber(pageNumber - 1);
+ }
+ };
+
+ const pageNumberInc = () => {
+ if (pageNumber < numPages) {
+ setPageNumber(pageNumber + 1);
+ }
+ };
+
+ const togglePage = () => {
+ setDisplayPage(!displayPage);
+ };
+
+ return (
+
+
+
+
+
+
{ setUnountOnFile(event.target.checked); }}
+ />
+
+
+
+ Page:
+ { pageNumber }
+
+
+
+ { !display ? null :
}
+ { !displayPage || !document
+ ? null
+ : (
+
+ ) }
+
+
+ );
+};
+
+TestSeparateDocumentAndPage.propTypes = {
+ file: propTypeIsFile,
+};