2

I am using the following URL format to preview a PDF ContentVersion file inside a LWC:

/sfc/servlet.shepherd/version/renditionDownload?
  rendition=SVGZ&versionId=0687Z000002EkVc&operationContext=CHATTER

But this just displays the first page of the PDF.

How can I preview an entire PDF?

0

3 Answers 3

4
+50

The given URL is just lacking a "page" parameter in order to download specific pages. E.g.

/sfc/servlet.shepherd/version/renditionDownload?rendition=SVGZ&versionId=0687Z000002EkVc&operationContext=CHATTER&page=2

downloads the second page. I'm unaware of any means to know the number of preview pages though. As a workaround one can render as many img tags for pages as can be successfully downloaded. A successful download takes a little time, but can be verified in Javascript by testing the naturalWidth of the img tag. The following LWC demonstrates this approach.

HTML

<template>
    <div lwc:ref="preview"></div>
</template>

Javascript

/* eslint-disable @lwc/lwc/no-async-operation */
import { LightningElement } from 'lwc';

export default class DisplayPdf extends LightningElement {

    img;
    page = 0;
    milliseconds = 100;
    renderAttemptNumber = 0;
    versionId = '068J6000006Gco6IAC';
    hasRendered = false;

    renderedCallback() {
        if(this.hasRendered) {
            return;
        }
        this.hasRendered = true;
        this.appendImage();
    }
    
    appendImage() {
        if(!this.img || this.img.naturalWidth > 0) {
            this.img = document.createElement('img');
            this.img.src = `/sfc/servlet.shepherd/version/renditionDownload?rendition=SVGZ&versionId=${this.versionId}&operationContext=CHATTER&page=${this.page}`;
            this.refs.preview.appendChild(this.img);
            this.page++;
            this.renderAttemptNumber = 0;
            setTimeout(() => {this.appendImage();}, this.milliseconds);
        } else {
            this.renderAttemptNumber++;
            if(this.renderAttemptNumber < 10) {
                setTimeout(() => {this.appendImage();}, this.milliseconds);
            } else {
                this.img.remove();
            }
        }
    }
}

The img.remove() makes sure no broken images are shown in the page (longer than a a second or so).

Here is some related information (although most of it is not about previews, but the actual file). Nowadays, in most cases where a link suffices, the NavigationMixin might do the job.

1

I was able to preview a entire ContentVersion file using a visualforce page:

Page:

<apex:page controller="PreviewContentVersionCTR">
    <apex:iframe src="data:application/pdf;base64,{!versionData}" height="700px"/>
</apex:page>

Controller:

public class PreviewContentVersionCTR {

    private final String versionData;

    public PreviewContentVersionCTR() {
        ContentVersion cv = [SELECT Id, VersionData FROM ContentVersion LIMIT 1];       
        versionData = EncodingUtil.base64Encode(cv.VersionData);
    }

    public String getVersionData() {
        return versionData;
    }
}
1
  • This may not work for large PDFs due to limits on Apex Heap size and/or VF state size. Commented Oct 11 at 16:47
0

Here's where I landed for ContentDocument previews. It doesn't show the entire file initially, but clicking the resulting first page render opens the full document preview, which was a viable workaround for us.

BASE_URL + '/lightning/r/ContentDocument/' + ContentDocument.Id + '/view'

Note that I'm using Id and not something like LatestPublishedVersionId, which is a different entity and doesn't work in this scenario.

I would still prefer to get the built-in document previewer that Salesforce loads on standard related lists. It's in-page and more feature-rich.

3
  • Hello isherwood! The provided link is pointing to the page with the Details and Preview tab of the ContentDocument, among other things - fair enough! My apologies in case you already noticed: This page uses just the API that I pointed out in my answer. E.g. open your page in Chrome DevTools, open the Network tab, clear logs, click on the document of the page to load the previews and search for /aura?r=29&ui-content-components-forceContent-previewInfoProvider.PreviewInfoProvider.getPreviewInfo=1 (or similar) in request URLs. The Response will list all the preview pages in one go :-) Commented Oct 18 at 14:38
  • Thanks, but I'm not sure how you're proposing I implement that. It doesn't contain a document ID.
    – isherwood
    Commented Oct 18 at 14:47
  • 1
    We can't use the /aura... request utilized by Salesforce, unfortunately. (In fact the request contains the ContentDocument ID in the POST body. Look under "Form Data" in Chrome.) Even if we could send requests to this endpoint (which Salesforce will make very hard), it might change tomorrow. If one wants to build one's own document viewer, I'm afraid one needs to use some strategy as the one outlined by my answer. Commented Oct 18 at 15:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .