I will create a custom lightning web component to convert the files on file upload.
To import the library you can follow steps 1-3 from below link
https://www.salesforcebolt.com/2021/09/create-custom-PDF-in-Lightning-Web-Component.html
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <template> <lightning-spinner if:true={isLoading} alternative-text="Loading" size="small" ></lightning-spinner> <div class="slds-m-around_small"> <lightning-input label="" name="file uploader" onchange={handleFilesChange} type="file" multiple ></lightning-input> </div> <div class="slds-m-around_small"> <template if:true={fileName}> {fileName} {fileSize} </template> </div> </template> |
JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | import { LightningElement, api } from "lwc"; import saveTheChunkFile from "@salesforce/apex/FileUploadService.saveTheChunkFile"; import { ShowToastEvent } from "lightning/platformShowToastEvent"; import PDF_LIB from "@salesforce/resourceUrl/pdflib"; import { loadScript } from "lightning/platformResourceLoader"; const MAX_FILE_SIZE = 4500000; const CHUNK_SIZE = 750000; export default class ConvertImagetoPDF extends LightningElement { @api recordId; fileName = ""; filesUploaded = []; isLoading = false; fileSize; filetype; renderedCallback() { loadScript(this, PDF_LIB).then(() => {}); } handleFilesChange(event) { if (event.target.files != null) { this.processFilesToConvert(event.target.files); } } async processFilesToConvert(files) { if (files.length > 0) { for (let i = 0; i < files.length; i++) { await this.createFileContent(files[i]); } } } async createFileContent(file) { this.showSpinner = true; this.fileName = file.name; this.filetype = file.type; var reader = new FileReader(); var self = this; reader.onload = function () { var fileContents = reader.result; var base64Mark = "base64,"; var dataStart = fileContents.indexOf(base64Mark) + base64Mark.length; fileContents = fileContents.substring(dataStart); if (self.filetype != "application/pdf") self.embedImageFile(fileContents, self.filetype); else self.prepareFileToUpload(fileContents); }; reader.readAsDataURL(file); await new Promise((resolve, reject) => setTimeout(resolve, 3000)); } async embedImageFile(file, filetype) { const pdfDoc = await PDFLib.PDFDocument.create(); let imageFile = ""; if (filetype == "image/png") imageFile = await pdfDoc.embedPng(file); else if (filetype == "image/jpeg") imageFile = await pdfDoc.embedJpg(file); let imageDims = imageFile; const page = pdfDoc.addPage(); if (imageFile.width > 595) { const scaleValue = parseFloat(595 / imageFile.width); imageDims = imageFile.scale(scaleValue); } page.drawImage(imageFile, { x: 0, y: page.getHeight() - imageDims.height, width: imageDims.width, height: imageDims.height }); const pdfBytes = await pdfDoc.save(); this.prepareFileToUpload(pdfBytes); } prepareFileToUpload(pdfBytes) { var blob = new Blob([pdfBytes], { type: "application/pdf" }); this.fileSize = this.formatBytes(blob.size, 2); if (blob.size > MAX_FILE_SIZE) { let message = "File size cannot exceed " + MAX_FILE_SIZE + " bytes.\n" + "Selected file size: " + blob.size; this.dispatchEvent( new ShowToastEvent({ title: "Error", message: message, variant: "error" }) ); return; } var reader = new FileReader(); var self = this; reader.onload = function () { var fileContents = reader.result; var base64Mark = "base64,"; var dataStart = fileContents.indexOf(base64Mark) + base64Mark.length; fileContents = fileContents.substring(dataStart); if (self.filetype != "application/pdf") self.upload(blob, fileContents); else self.upload(blob, pdfBytes); }; reader.readAsDataURL(blob); } upload(file, fileContents) { var fromPos = 0; var toPos = Math.min(fileContents.length, fromPos + CHUNK_SIZE); this.uploadChunk(file, fileContents, fromPos, toPos, ""); } uploadChunk(file, fileContents, fromPos, toPos, attachId) { this.isLoading = true; var chunk = fileContents.substring(fromPos, toPos); saveTheChunkFile({ parentId: this.recordId, fileName: file.name, base64Data: encodeURIComponent(chunk), contentType: file.type, fileId: attachId }) .then((result) => { attachId = result; fromPos = toPos; toPos = Math.min(fileContents.length, fromPos + CHUNK_SIZE); if (fromPos < toPos) { this.uploadChunk(file, fileContents, fromPos, toPos, attachId); } else { this.dispatchEvent( new ShowToastEvent({ title: "Success!", message: "File Upload Success", variant: "success" }) ); this.isLoading = false; } }) .catch((error) => { console.error("Error: ", error); }) .finally(() => {}); } formatBytes(bytes, decimals) { if (bytes == 0) return "0 Bytes"; var k = 1024, dm = decimals || 2, sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i]; } } |
APEX
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | public with sharing class FileUploadService { @AuraEnabled public static Id saveTheChunkFile(Id parentId, String fileName, String base64Data, String contentType, String fileId){ base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8'); if ( String.isBlank(fileId) ) { fileId = saveFiles(parentId, fileName, base64Data ); } else { appendToFile(fileId, base64Data); } return Id.valueOf(fileId); } @AuraEnabled public static Id saveFiles(Id recordId, String fileName, String base64Data ) { ContentVersion contentToInsert =new ContentVersion(); contentToInsert.Title =fileName; contentToInsert.VersionData=EncodingUtil.base64Decode(base64Data); contentToInsert.PathOnClient='CustomPDF.pdf' ; contentToInsert.IsMajorVersion = false; contentToInsert.Title = 'ConvertedtoPDF'; insert contentToInsert; contentToInsert = [select id, ContentDocumentId from ContentVersion WHERE Id =: contentToInsert.Id]; ContentDocumentLink cl = new ContentDocumentLink(); cl.ContentDocumentId = contentToInsert.ContentDocumentId; cl.LinkedEntityId = recordId; cl.ShareType = 'V'; cl.Visibility = 'AllUsers'; insert cl; return contentToInsert.id; } @AuraEnabled public static void appendToFile(Id contentDocumentId, String base64Data) { //base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8'); ContentVersion versionData = [ SELECT Id, VersionData,ContentDocumentId FROM ContentVersion WHERE Id = :contentDocumentId ]; String existingBody = EncodingUtil.base64Encode(versionData.VersionData); versionData.VersionData = EncodingUtil.base64Decode(existingBody + base64Data); update versionData; } @AuraEnabled public static List<FileDescriptor> getEntityRecordFiles(List<String> listIds) { List<FileDescriptor> files = new List<FileDescriptor>(); Set<Id> recordIds = new Set<Id>(); for(String i:listIds){ recordIds.add(i); } if (recordIds.size() == 0) { return files; } Map<Id,ContentVersion> versionsMap = new Map<Id, ContentVersion>([ SELECT Id,VersionData, Title, ContentDocumentId, FileExtension FROM ContentVersion WHERE Id = :recordIds AND IsLatest = TRUE WITH SECURITY_ENFORCED ]); for(String versionId : listIds){ ContentVersion cv = versionsMap.get(versionId); FileDescriptor data = new FileDescriptor(); data.Content = EncodingUtil.base64Encode(cv.VersionData); data.ContentType = ContentType(cv.FileExtension); data.ContentDocumentId = cv.ContentDocumentId; files.add(data); } return files; } public static string ContentType(string fileType) { switch on fileType.toLowerCase() { when 'docx' { return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; } when 'csv' { return 'application/vnd.ms-excel'; } when 'wav' { return 'audio/wav'; } when 'wmv' { return 'video/x-ms-wmv'; } when 'mp3' { return 'audio/mpeg'; } when 'mp4' { return 'video/mp4'; } when 'png' { return 'image/png'; } when 'pdf' { return 'application/pdf'; } when else { return 'image/jpeg'; } } } } |
OUTPUT
Checkout complete video tutorial below
If you have any question please leave a comment below.
If you would like to add something to this post please leave a comment below.
Share this blog with your friends if you find it helpful somehow !
Thanks
Happy Coding :)
4 Comments
Hi. seems like apex class attribute FileDescriptor can't found is salesforce "public static List is not , do you mind sharing
ReplyDeleteHere you go
Deletepublic with sharing class FileDescriptor {
@AuraEnabled
public string content { get; set; }
@AuraEnabled
public string contentType { get; set; }
@AuraEnabled
public string contentDocumentId { get; set; }
public FileDescriptor() {
}
}
This comment has been removed by the author.
ReplyDeleteBro how to add this component in screen flow and placed that quick actions button in work order object ?
Delete