react-pdf icon indicating copy to clipboard operation
react-pdf copied to clipboard

It will be very helpful if this plugin has feature to render editable pdf

Open salildts opened this issue 9 months ago • 4 comments

Before you start - checklist

  • [X] I understand that React-PDF does not aim to be a fully-fledged PDF viewer and is only a tool to make one
  • [X] I have checked if this feature request is not already reported

Description

I'm using the react-pdf plugin to render a editable pdf by which I can fill the form of the given pdf and then can download it with the given inputs in the pdf. But I could not get any scope to make the things ready for us. So, my request is to add this feature and this plug in will be more helpful for us.

Proposed solution

No response

Alternatives

No response

Additional information

No response

salildts avatar May 01 '24 15:05 salildts

Did you find any solution. i want to implement same feature as your. tried using pdfjs-dist in next 14 but getting a shit ton of errors which i could not resolve.

Code-X-Rahul avatar May 02 '24 18:05 Code-X-Rahul

have you tried setting renderForm={true} on the Page component?

mikejar avatar May 08 '24 14:05 mikejar

Like @mikejar said you can use renderForm to render annotations, and if you want to download the modified pdf you can use:

const pdfRef = React.useRef<DocumentCallback>(null);

const onDocumentLoadSuccess = (pdf) => {
  pdfRef.current = pdf;
};

const downloadPdf = async () => {
  const data = await pdfRef.current?.saveDocument();
  downloadManager.download(data, null, "result.pdf", null);
};
 
// downloadManager, only support web browser environment
import { createValidAbsoluteUrl, isPdfFile } from "pdfjs-dist";

function download(blobUrl, filename) {
  const a = document.createElement("a");
  if (!a.click) {
    throw new Error('DownloadManager: "a.click()" is not supported.');
  }
  a.href = blobUrl;
  a.target = "_parent";
  // Use a.download if available. This increases the likelihood that
  // the file is downloaded instead of opened by another PDF plugin.
  if ("download" in a) {
    a.download = filename;
  }
  // <a> must be in the document for recent Firefox versions,
  // otherwise .click() is ignored.
  (document.body || document.documentElement).append(a);
  a.click();
  a.remove();
}

/**
 * @implements {IDownloadManager}
 */
class DownloadManager {
  private openBlobUrls = new WeakMap();

  downloadUrl(url, filename, _options) {
    if (!createValidAbsoluteUrl(url, "http://example.com")) {
      console.error(`downloadUrl - not a valid URL: ${url}`);
      return; // restricted/invalid URL
    }
    download(url + "#pdfjs.action=download", filename);
  }

  downloadData(data, filename, contentType) {
    const blobUrl = URL.createObjectURL(
      new Blob([data], { type: contentType })
    );
    download(blobUrl, filename);
  }

  /**
   * @returns {boolean} Indicating if the data was opened.
   */
  openOrDownloadData(data, filename, dest = null) {
    const isPdfData = isPdfFile(filename);
    const contentType = isPdfData ? "application/pdf" : "";

    if (isPdfData) {
      let blobUrl = this.openBlobUrls.get(data);
      if (!blobUrl) {
        blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
        this.openBlobUrls.set(data, blobUrl);
      }
      let viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
      if (dest) {
        viewerUrl += `#${escape(dest)}`;
      }

      try {
        window.open(viewerUrl);
        return true;
      } catch (ex) {
        console.error(`openOrDownloadData: ${ex}`);
        // Release the `blobUrl`, since opening it failed, and fallback to
        // downloading the PDF file.
        URL.revokeObjectURL(blobUrl);
        this.openBlobUrls.delete(data);
      }
    }

    this.downloadData(data, filename, contentType);
    return false;
  }

  download(data, url, filename, _options) {
    const blobUrl = URL.createObjectURL(
      new Blob([data], { type: "application/pdf" })
    );
    download(blobUrl, filename);
  }
}

export { DownloadManager };

nothingrealhappen avatar Jun 11 '24 16:06 nothingrealhappen

Like @mikejar said you can use renderForm to render annotations, and if you want to download the modified pdf you can use:

const pdfRef = React.useRef<DocumentCallback>(null);

const onDocumentLoadSuccess = (pdf) => {
  pdfRef.current = pdf;
};

const downloadPdf = async () => {
  const data = await pdfRef.current?.saveDocument();
  downloadManager.download(data, null, "result.pdf", null);
};
 
// downloadManager, only support web browser environment
import { createValidAbsoluteUrl, isPdfFile } from "pdfjs-dist";

function download(blobUrl, filename) {
  const a = document.createElement("a");
  if (!a.click) {
    throw new Error('DownloadManager: "a.click()" is not supported.');
  }
  a.href = blobUrl;
  a.target = "_parent";
  // Use a.download if available. This increases the likelihood that
  // the file is downloaded instead of opened by another PDF plugin.
  if ("download" in a) {
    a.download = filename;
  }
  // <a> must be in the document for recent Firefox versions,
  // otherwise .click() is ignored.
  (document.body || document.documentElement).append(a);
  a.click();
  a.remove();
}

/**
 * @implements {IDownloadManager}
 */
class DownloadManager {
  private openBlobUrls = new WeakMap();

  downloadUrl(url, filename, _options) {
    if (!createValidAbsoluteUrl(url, "http://example.com")) {
      console.error(`downloadUrl - not a valid URL: ${url}`);
      return; // restricted/invalid URL
    }
    download(url + "#pdfjs.action=download", filename);
  }

  downloadData(data, filename, contentType) {
    const blobUrl = URL.createObjectURL(
      new Blob([data], { type: contentType })
    );
    download(blobUrl, filename);
  }

  /**
   * @returns {boolean} Indicating if the data was opened.
   */
  openOrDownloadData(data, filename, dest = null) {
    const isPdfData = isPdfFile(filename);
    const contentType = isPdfData ? "application/pdf" : "";

    if (isPdfData) {
      let blobUrl = this.openBlobUrls.get(data);
      if (!blobUrl) {
        blobUrl = URL.createObjectURL(new Blob([data], { type: contentType }));
        this.openBlobUrls.set(data, blobUrl);
      }
      let viewerUrl = "?file=" + encodeURIComponent(blobUrl + "#" + filename);
      if (dest) {
        viewerUrl += `#${escape(dest)}`;
      }

      try {
        window.open(viewerUrl);
        return true;
      } catch (ex) {
        console.error(`openOrDownloadData: ${ex}`);
        // Release the `blobUrl`, since opening it failed, and fallback to
        // downloading the PDF file.
        URL.revokeObjectURL(blobUrl);
        this.openBlobUrls.delete(data);
      }
    }

    this.downloadData(data, filename, contentType);
    return false;
  }

  download(data, url, filename, _options) {
    const blobUrl = URL.createObjectURL(
      new Blob([data], { type: "application/pdf" })
    );
    download(blobUrl, filename);
  }
}

export { DownloadManager };

Much credits for the DownloadManager solution. Really helps a lot. But does the solution come from https://github.com/mozilla/pdf.js/blob/master/web/download_manager.js originally?

zhanls avatar Jul 03 '24 10:07 zhanls

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 14 days.

github-actions[bot] avatar Oct 07 '24 00:10 github-actions[bot]

This issue was closed because it has been stalled for 14 days with no activity.

github-actions[bot] avatar Oct 21 '24 00:10 github-actions[bot]