Salesforce Asked on November 13, 2021
I have a very simple LWC that I am trying to use to compress image files (that happen to be Salesforce attachments). Here is the complete JS:
import { LightningElement, api } from 'lwc';
export default class ImageCompressor extends LightningElement {
statusMessage = 'Ready'; // String
constructor() {
super();
}
@api compressImage(imageURL) {
let img = new Image();
img.addEventListener('load', function() {
debugger;
let canvas = document.createElement('canvas');
let width = img.width;
let height = img.height;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
let compressedImage = canvas.toDataURL('image/jpeg', 0.5);
this.statusMessage = 'Compression complete';
const e = new CustomEvent('compressioncomplete', { detail: compressedImage, bubbles: true });
this.dispatchEvent(e);
}, false);
img.src = imageURL;
this.statusMessage = 'Compression started.'
debugger;
}
}
I invoke it via its api method in a parent LWC component, passing in the URL of an attachment file:
compressHandler() {
let url = this.getImageURL(this.imageList[1].Id);
debugger;
this.template.querySelector('c-image-compressor').compressImage(url);
}
getImageURL(imageId) {
return '/servlet/servlet.FileDownload?file=' + imageId;
}
It looks like the code is working fine (the image appears to load OK) but the script errors out at the canvas.toDataURL() line. Hard to interpret the error but everything is working until this line executes.
Any thoughts? Thanks for your help!
In case someone is looking to compress image on client side before uploading to salesforce. Apex getter is not used here. "handleUploadFile()" is called on change event of lightning-input component
handleUploadFile(event) {
const file = event.target.files[0]
let img = new Image();
img.onload = () => {
debugger;
let canvas = document.createElement('canvas');
let width = img.width;
let height = img.height;
canvas.width = width;
canvas.height = height;
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
let compressedImage = canvas.toDataURL('image/jpeg', 0.5);
this.statusMessage = 'Compression complete';
var base64 = compressedImage.split(',')[1];
this.fileData = {
'filename': file.name,
'base64': base64,
'recordId': this.recordId
}
// Call apex imperatively here to upload the image to the desired record
console.log(this.fileData)
}
img.src = URL.createObjectURL(file);
this.statusMessage = 'Compression started.'
}
Answered by Abhijeet on November 13, 2021
I figured it out. I created a an apex getter that returns the image body as a base64 string and then I use a data URI when constructing the image object.
Does not fall foul of security and works like a charm, even for multi-megabyte files.
Answered by Dave C on November 13, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP