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 :
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 | < 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 :
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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | 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' ; UserName = 'skycloudd' ; 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() { 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(); 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 :
1 2 3 4 5 6 7 8 | <? xml version = "1.0" ?> < apiVersion >54.0</ apiVersion > < isExposed >true</ isExposed > < targets > < target >lightning__HomePage</ target > </ targets > </ LightningComponentBundle > |