Hello friends, today we are going to discuss Upload Image by HTTP Callout in LWC Salesforce. We will upload the images to the Imgur server by API request in LWC without APEX Call. We use the FETCH method to get and delete the images from the Imgur. We upload the files by XMLHttpRequest so we can track them by the progress bar.
Also, check this: Make HTTP Callout Request in LWC Salesforce
Key Highlights :
- Call HTTP Callout via LWC.
- Without the use of Apex Class.
- Fetch the all files
- Delete the Image file
- Upload the image with the progress bar.
- Authorisation in LWC
Process & Code :
Step 1: Create Account in the Imgur.
Step 2: Create App by clicking this Link and chose without Callback URL. After creating App you will get the Client Id and Client Secret. Put this in a safe place for our next step Authorization.
Step 3: Authorized and get Access Token by the below link , in the below link put your Client Id and run this link in the browser. You will get the redirect URL with Access Token and other info. Store the Access token for further use.
https://api.imgur.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=token&state=test
Redirect URL: https://example.com/oauthcallback#access_token=ACCESS_TOKEN&token_type=Bearer&expires_in=3600
Step 4: Set up the CSP Trusted Sites of this Endpoint URL GO Setup > CSP Trusted Sites > Click New Trusted Site and create new records by filling in Endpoint and name. EndPoint ==> https://api.imgur.com
Step 5: Now We create the LWC component. Here I create two cards, in one card I upload the files, and on the other one display and delete the images.
lWCFileUploadCallout.HTML :
<template>
<lightning-card title="Http Callout With Imgur In LWC" icon-name="standard:logging">
<div class="slds-var-p-around_small">
<lightning-layout multiple-rows>
<lightning-layout-item padding="around-small" size="12" medium-device-size="12" large-device-size="12">
<lightning-input label="" name="file uploader" onchange={handleFilesChange} type="file" multiple>
</lightning-input>
<div class="slds-text-body_small slds-text-color_error">{fileName}</div>
</lightning-layout-item>
<lightning-layout-item padding="around-small" size="12" medium-device-size="12" large-device-size="12">
<lightning-progress-bar value={progress} size="medium" variant="circular"></lightning-progress-bar> {progress}%
</lightning-layout-item>
<!--<lightning-layout-item padding="around-small" size="12" medium-device-size="12" large-device-size="12">
<p><b>Image Link :</b> {imglink}</p>
<img src={imglink}/>
</lightning-layout-item>-->
<lightning-layout-item size="12" class="slds-var-p-top_small">
<lightning-button class="slds-align_absolute-center" variant="brand" label="Upload"
onclick={handleSave} disabled={isDisable}></lightning-button>
</lightning-layout-item>
</lightning-layout>
</div>
</lightning-card>
<div class="slds-m-top_x-small"></div>
<lightning-card title="Http Callout With Imgur In LWC" icon-name="doctype:image" >
<template if:true={showLoadingSpinner}>
<lightning-spinner alternative-text="Loading" size="medium" class="spinnerClass"></lightning-spinner>
</template>
<lightning-layout multiple-rows if:true={imageData}>
<lightning-layout-item padding="around-small" size="3" for:each={imageData} for:item="img" key={img.bandwidth}>
<div class="responsive">
<div class="gallery">
<a target="_blank" href={img.link}>
<img src={img.link} alt={img.title}>
</a>
<div class="desc">
<lightning-button class="slds-align_absolute-center" variant="destructive" label="Delete"
onclick={deleteImage} data-name={img.deletehash}>
</lightning-button>
</div>
</div>
</div>
</lightning-layout-item>
</lightning-layout>
</lightning-card>
</template>
lWCFileUploadCallout.JS :
import { LightningElement, track, api } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class LWCFileUploadCallout extends LightningElement {
@track fileName = '';
@track UploadFile = 'Upload File';
@track showLoadingSpinner = false;
@track isDisable = false;
@track imglink;
selectedRecords;
filesUploaded = [];
file;
fileContents;
fileReader;
content;
@track progress = 0;
@track imageData;
MAX_FILE_SIZE = 1500000;
ACCESS_TOKEN = 'xxxxxxxxxxxx';
CLIENT_ID = 'xxxxxxxxxxx';
Upload_Image_EndPoint = 'https://api.imgur.com/3/image';
UserName = 'skycloudd';
Fetch_Image_EndPoint = 'https://api.imgur.com/3/account/' + this.UserName + '/images';
Delete_Image_EndPoint = 'https://api.imgur.com/3/account/' + this.UserName + '/image/';
connectedCallback() {
this.getAllFiles();
}
// getting file
handleFilesChange(event) {
if (event.target.files.length > 0) {
this.filesUploaded = event.target.files;
this.fileName = event.target.files[0].name;
}
}
handleSave() {
if (this.filesUploaded.length > 0) {
this.uploadHelper();
} else {
this.fileName = 'Please select file to upload!!';
}
}
uploadHelper() {
this.file = this.filesUploaded[0];
if (this.file.size > this.MAX_FILE_SIZE) {
window.console.log('File Size is to long');
return;
}
this.showLoadingSpinner = true;
// create a FileReader object
this.fileReader = new FileReader();
// set onload function of FileReader object
this.fileReader.onloadend = (() => {
this.fileContents = this.fileReader.result;
let base64 = 'base64,';
this.content = this.fileContents.indexOf(base64) + base64.length;
this.fileContents = this.fileContents.substring(this.content);
//call the uploadProcess method
this.handleFileUpload();
});
this.fileReader.readAsDataURL(this.file);
}
handleFileUpload() {
//https://api.imgur.com/oauth2/authorize?
client_id=YOUR_CLIENT_ID&response_type=REQUESTED_RESPONSE_TYPE&state=APPLICATION_STATE
//above request for get access token use in our code
this.isDisable = true;
this.progress = 0;
var formData = new FormData();
formData.append("title", this.fileName);
formData.append("type", this.filetype);
formData.append("image", this.filesUploaded[0]);
//console.log(progressBar);
var xhr = new XMLHttpRequest();
var url = 'https://api.imgur.com/3/image';
xhr.open("POST", url, true);
//xhr.setRequestHeader("Content-Type", "application/json");
//xhr.setRequestHeader("Accept", "application/json");
//xhr.setRequestHeader("Authorization", "Client-ID xxxxxx");
xhr.setRequestHeader("Authorization", "Bearer " + this.ACCESS_TOKEN);
//xhr.setRequestHeader("token", "xxxxxxxxxxxxxxxxxxxxxxx");
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
this.showToast('File Uploaded', this.file.name + '- Uploaded Successfully!!!', 'success', 'dismissable');
var json = JSON.parse(xhr.responseText);
console.log(json);
this.imglink = json.data.link;
this.getAllFiles();
this.showLoadingSpinner = false;
this.isDisable = false;
}
};
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
var ratio = Math.floor((e.loaded / e.total) * 100);
console.log(ratio);
this.progress = ratio;
}
}
xhr.upload.onloadstart = (e) => {
console.log(e);
}
xhr.upload.onloadend = (e) => {
console.log(e);
}
xhr.onerror = (error) => {
console.log(error);
}
xhr.send(formData);
}
getAllFiles(){
this.showLoadingSpinner = true;
var userName = 'skycloudd';
var link = this.Fetch_Image_EndPoint;
fetch(
link,
{
method: "GET",
headers: {
//contentType: "application/json",
"Authorization": "Bearer " + this.ACCESS_TOKEN,
}
}
).then((response) => {
console.log(response);
this.showLoadingSpinner = false;
return response.json();
}).then((jsonResponse) => {
console.log(jsonResponse);
this.imageData = jsonResponse.data;
this.showLoadingSpinner = false;
}).catch(error => {
this.showLoadingSpinner = false;
window.console.log('callout error ===> ' + JSON.stringify(error));
})
}
deleteImage(event){
this.showLoadingSpinner = true;
var deleteHashId = event.target.dataset.name;
var link = this.Delete_Image_EndPoint + deleteHashId;
fetch(
link,
{
method: "DELETE",
headers: {
"Authorization": "Bearer " + this.ACCESS_TOKEN,
}
}
).then((response) => {
console.log(response);
this.showLoadingSpinner = false;
return response.json();
}).then((jsonResponse) => {
this.showToast('File Deleted', 'File Deleted Successfully!!!', 'success', 'dismissable');
this.getAllFiles();
console.log(jsonResponse);
this.showLoadingSpinner = false;
}).catch(error => {
this.showLoadingSpinner = false;
window.console.log('callout error ===> ' + JSON.stringify(error));
})
}
showToast(title, message, variant, mode) {
const evt = new ShowToastEvent({
title: title,
message: message,
variant: variant,
mode: mode
});
this.dispatchEvent(evt);
}
}
lWCFileUploadCallout.CSS :
div.gallery {
border: 1px solid #ccc;
}
div.gallery:hover {
border: 1px solid #777;
}
div.gallery img {
width: 100%;
height: 300px;
}
div.desc {
padding: 15px;
text-align: center;
}
* {
box-sizing: border-box;
}
.responsive {
padding: 0 6px;
float: left;
//width: 24.99999%;
}
lWCFileUploadCallout.js-meta.xml :
<?xml version="1.0"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>54.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>