> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/salesforce/content-edit/convert-documents-salesforce.md).

# Convert documents in Salesforce

Learn how to convert documents in Salesforce using WebViewer. Follow step-by-step instructions in config.js for PDF, DOCX, XLSX, PPTX, JPG, PNG, TIFF conversions. Explore a sample project on GitHub fo

## Getting Started

We recommend the [Overview](/salesforce/get-started/readme.md) page to learn how to correctly use a `config.js` before getting started with using Webviewer.

<a href="https://github.com/ApryseSDK/salesforce-webviewer-document-converter" class="button primary">Sample Project</a>

## Convert an Open Document

To convert a document, first you'll need to open a document in our lightning web componenet where the Webviewer is mounted in an iFrame (in our sample, it is `pdftronWvInstance`).

Once a document is loaded and viewable in our preview screen, you'll be allowed to convert documents in our available formats:

* PDF, PDF/A
* DOCX, XLSX, PPTX (MS Office software or licenses are not required)
* JPG, PNG, TIFF

We store the open document into an object and label it as `payload`. Storing the neccessary information for conversion and saving the converted file onto salesforce.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
handleBlobSelected(record) {
    const blobby = new Blob([_base64ToArrayBuffer(record.body)], {
      type: mimeTypes[record.FileExtension]
    });
    const payload = {
      blob: blobby,
      extension: record.cv.FileExtension,
      file: record.cv.Title,
      filename: record.cv.Title + "." + record.cv.FileExtension,
      documentId: record.cv.Id
    };

    this.payload = {...payload};
    this.iframeWindow.postMessage({ type: 'OPEN_DOCUMENT_BLOB', payload }, '*');
  }
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Convert in your config.js

Since WebViewer is hosted in an iFrame, we need to use our `config.js` file to access our WebViewer instance. You need to post a message to your `iframeWindow` like so:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
this.iframeWindow.postMessage({type: 'CONVERT DOCUMENT', payload }, '*');
```

{% endcode %}
{% endtab %}
{% endtabs %}

In a Salesforce deployment, the equivalent of `instance` is [`readerControl`](/web/advanced/config-files.md#accessing-webviewer-instance-from-the-config-file).

### Standard conversion to pdf

In your `config.js` file, you can you listen for messages posted to the iFrame by registering an event listener using `window.addEventListener("message", this.handleReceiveMessage)`. In this case, `handleReceiveMessage` is a function that handles these posted messages. You can review the snippet below for an example of how to deal with posted messages.

This snippet uses the instance of Webviewer and converts the loaded document as a PDF. When downloaded, we are allowed to download from the instance using our API call `downloadPdf()`. Writing to Salesforce we have to grab file data and return the converted data back to the lwc with a event listener.

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
async function toPdf (payload, transport) {
  if (transport){
      const doc = instance.Core.documentViewer.getDocument();
      const buffer = await doc.getFileData({ downloadType: payload.exportType });
      const bufferFile = new Uint8Array(buffer);

      saveFile(bufferFile, payload.file, "." + payload.exportType);

  } else {
      let file = payload.file;

      parent.postMessage({ type: 'DOWNLOAD_DOCUMENT', file }, '*');
      instance.downloadPdf({filename: payload.file});
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
handleReceiveMessage = (event) => {
    const me = this;
    if (event.isTrusted && typeof event.data === 'object') {
      switch (event.data.type) {
        case 'SAVE_DOCUMENT':
          const cvId = event.data.payload.contentDocumentId;
          saveDocument({ json: JSON.stringify(event.data.payload), recordId: this.recordId ? this.recordId : '', cvId: cvId })
          .then((response) => {
            me.iframeWindow.postMessage({ type: 'DOCUMENT_SAVED', response }, '*');
            
            fireEvent(this.pageRef, 'refreshOnSave', response);

            fireEvent(this.pageRef, 'finishConvert', '');
            this.showNotification('Success', event.data.payload.filename + ' Saved', 'success');
          })
          .catch(error => {
            me.iframeWindow.postMessage({ type: 'DOCUMENT_SAVED', error }, '*')
            fireEvent(this.pageRef, 'refreshOnSave', error);
            console.error(event.data.payload.contentDocumentId);
            console.error(JSON.stringify(error));
            this.showNotification('Error', error.body, 'error');
          });
          break;
        case 'DOWNLOAD_DOCUMENT':
          const body = event.data.file + ' Downloaded';
          fireEvent(this.pageRef, 'finishConvert', '');
          this.showNotification('Success', body, 'success');
          break;
        default:
          break;
      }
    }
  }
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Conversion to image files

Similar to standard conversion to pdf, all conversions including pdf to image files would converted in `config.js` file.

The following snippet uses multiple namespaces in our API:

{% tabs %}
{% tab title="JavaScript" %}
{% code lineNumbers="true" %}

```js
const pdfToImage = async (payload, transport) => {

  await PDFNet.initialize();

  let doc = null;

  await PDFNet.runWithCleanup(async () => {

    const buffer = await payload.blob.arrayBuffer();
    doc = await PDFNet.PDFDoc.createFromBuffer(buffer);
    doc.initSecurityHandler();
    doc.lock();

    const count = await doc.getPageCount();
    const pdfdraw = await PDFNet.PDFDraw.create(92);
    
    let itr;
    let currPage;
    let bufferFile;

    // Handle multiple pages
    for (let i = 1; i <= count; i++){

      itr = await doc.getPageIterator(i);
      currPage = await itr.current();
      bufferFile = await pdfdraw.exportStream(currPage, payload.exportType.toUpperCase());
      transport ? saveFile(bufferFile, payload.file, "." + payload.exportType) : downloadFile(bufferFile, payload.file, "." + payload.exportType);

    }

  }); 

}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Sample project

You can review the Salesforce PDF App to showcase an end-to-end example of document conversion in [Github repository](https://github.com/ApryseSDK/salesforce-pdf-app/).

## Live demo

Check out this live [file conversion demo](https://showcase.apryse.com/pdfa-conversion) (hosted outside of Salesforce).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/salesforce/content-edit/convert-documents-salesforce.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
