I'm creating a PDF viewer using Visualforce and the PDF.js library. My project doesn't include react.
When I try to execute pdfjsLib.getDocument() passing the URL of a PDF stored in Salesforce itself, as an attachment (ContentDocument), I'm getting the following CORS error:
"Access to fetch at [...] redirected from [...] has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."
I have done the following when calling getDocument() and it still doesn't work:
- I specify the Access-Control-Allow-Origin as '*'
- I give a bearer authorization token
- I set "withCredentials: true"
- I have whitelisted all domains inside CORS configuration in Salesforce Setup
This is my call to the function getDocument():
document.getElementsByClassName("pdfFileSelector")[0].addEventListener('change', (event) => {
let fileId = event.target.value;
let currentUrl = window.location.href;
let domain = currentUrl.substring(0, currentUrl.indexOf('/', 8));
let fileUrl = domain + '/sfc/servlet.shepherd/document/download/' + fileId + '?origin=' + window.location.host;
console.log('>>> Url completo');
console.log(fileUrl);
pdfjsLib.getDocument({
url: fileUrl,
withCredentials: true,
httpHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Authorization': 'Bearer {!$Api.Session_ID}'
},
}).then((pdf) => {
myState.pdf = pdf;
render();
console.log('>>> Terminó de renderizar. funcionó?');
});
});
And these are all the domains that I'm whitelisting from Saelsforce > Setup > CORS:
None of these things have worked. Please help, any suggestion is greatly appreciated, since I've been dealing with this error for 3 days now, looking into any documentation and tutorial/question/forum available, still I'm stuck. Thank you
Here's my full Visualforce Code:
<apex:page controller="CSCACustomPDFPreviewController" lightningStylesheets="true" applyHtmlTag="false" showHeader="false" standardStylesheets="false" sidebar="false" docType="html-5.0">
<head>
<apex:slds/>
<apex:includeScript value="{!$Resource.PDFjsLibrary}"/>
<style>
.main-container {
border: 1px solid #C9C9C9;
border-radius: 2px;
}
.header-container {
display: flex;
align-items: center;
column-gap: 10px;
height: 50px;
background-color: #F3F3F3;
padding-left: 15px;
}
.body-container {
background-color: white;
padding: 15px;
border-top: 1px solid #C9C9C9;
}
.title-text {
font-size: 14px !important;
}
#canvas_container {
width: 100%;
height: 800px;
overflow: auto;
background: #333;
text-align: center;
border: solid 3px;
}
.pdfFileSelector {
width: 100%;
}
</style>
</head>
<body class="slds-scope">
<!-- Header and title of the card-->
<div class="header-container">
<span class="slds-icon_container slds-icon-standard-account" >
<svg aria-hidden="true" class="slds-icon slds-icon--small">
<use xmlns:xlink="http://www.w3.org/2000/xlink" xlink:href="/apexpages/slds/latest/assets/icons/doctype-sprite/svg/symbols.svg#pdf">
</use>
</svg>
</span>
<div class="slds-text-heading_small title-text"><b>Custom PDF Preview</b></div>
</div>
<!-- // Header and title of the card-->
<div class="body-container slds-is-relative slds-border_top">
<br/>
<!-- PDF file selector-->
<apex:form >
<label>Select a file name to display the preview</label>
<apex:selectList styleclass="pdfFileSelector" size="1">
<apex:selectOptions value="{!fileOptions}" />
</apex:selectList>
</apex:form>
<div>
<p>El resultado de llamad Resource.PDFjsLibrary</p>
{!$Resource.PDFjsLibrary}
</div>
<!--// PDF file selector-->
<br/>
<!-- Canvas to render PDF-->
<div id="my_pdf_viewer">
<div id="canvas_container">
<canvas id="pdf_renderer"></canvas>
</div>
<br/>
<div id="navigation_controls">
<button id="go_previous">Previous</button>
<input id="current_page" value="1" type="number"/>
<button id="go_next">Next</button>
</div>
<div id="zoom_controls">
<button id="zoom_in">+</button>
<button id="zoom_out">-</button>
</div>
</div>
<!--// Canvas to render PDF-->
</div>
<script>
pdfjsLib.GlobalWorkerOptions.workerSrc = '//airliquidehhc-amer--uat.sandbox.lightning.force.com{!$Resource.PDFjsWorker}';
var myState = {
pdf: null,
currentPage: 1,
zoom: 1
}
function render() {
myState.pdf.getPage(myState.currentPage).then((page) => {
var canvas = document.getElementById("pdf_renderer");
var ctx = canvas.getContext('2d');
var viewport = page.getViewport(myState.zoom);
canvas.width = viewport.width;
canvas.height = viewport.height;
page.render({
canvasContext: ctx,
viewport: viewport
});
});
}
document.getElementsByClassName("pdfFileSelector")[0].addEventListener('change', (event) => {
let fileId = event.target.value;
let currentUrl = window.location.href;
let domain = currentUrl.substring(0, currentUrl.indexOf('/', 8));
let fileUrl = domain + '/sfc/servlet.shepherd/document/download/' + fileId + '?origin=' + window.location.host;
console.log('>>> Url completo');
console.log(fileUrl);
pdfjsLib.getDocument({
url: fileUrl,
withCredentials: true,
httpHeaders: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET',
'Authorization': 'Bearer {!$Api.Session_ID}'
},
}).then((pdf) => {
myState.pdf = pdf;
render();
console.log('>>> Terminó de renderizar. funcionó?');
});
});
document.getElementById('go_previous').addEventListener('click', (e) => {
if(myState.pdf == null || myState.currentPage == 1)
return;
myState.currentPage -= 1;
document.getElementById("current_page").value = myState.currentPage;
render();
});
document.getElementById('go_next').addEventListener('click', (e) => {
if(myState.pdf == null || myState.currentPage > myState.pdf._pdfInfo.numPages)
return;
myState.currentPage += 1;
document.getElementById("current_page").value = myState.currentPage;
render();
});
document.getElementById('current_page').addEventListener('keypress', (e) => {
if(myState.pdf == null) return;
// Get key code
var code = (e.keyCode ? e.keyCode : e.which);
// If key code matches that of the Enter key
if(code == 13) {
var desiredPage =
document.getElementById('current_page').valueAsNumber;
if(desiredPage >= 1 && desiredPage <= myState.pdf._pdfInfo.numPages) {
myState.currentPage = desiredPage;
document.getElementById("current_page").value = desiredPage;
render();
}
}
});
document.getElementById('zoom_in').addEventListener('click', (e) => {
if(myState.pdf == null) return;
myState.zoom += 0.5;
render();
});
document.getElementById('zoom_out').addEventListener('click', (e) => {
if(myState.pdf == null) return;
myState.zoom -= 0.5;
render();
});
</script>
</body>
</apex:page>