File thumbnail preview and icon with Lightning File Upload in Lightning Web Component | Salesforce ☁️⚡️

 In this blog I will share the code to display the file thumbnail picture in a grid after uploading it using Lightning File Uploader.

It will create a gallery kind of layout on the page. Also we will display icon of file type in the block like if file type is PDF then it will display pdf icon & if the type is JPG then it will show image icon above it.

I have used two components here. In first component I am having my Lightning File Upload code to save the image and underneath that I am having a child component to display file preview in a card to show a gallery kind of layout.


Please check complete code below : 

PreviewFileThumbnails.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
<template>
  <lightning-file-upload
    name="fileUploader"
    accept={acceptedFormats}
    record-id={recordId}
    onuploadfinished={handleUploadFinished}
    multiple
  >
  </lightning-file-upload>

  <br />
  <div
    class="
      slds-page-header__row
      slds-var-m-top_x-small
      slds-var-m-left_medium
      slds-grid slds-wrap
    "
  >
    <ul class="slds-grid slds-wrap slds-gutters">
      <template if:true={loaded}>
        <template for:each={files} for:item="file">
          <c-preview-file-thumbnail-card
            key={file.Id}
            file={file}
            record-id={recordId}
            thumbnail={file.thumbnailFileCard}
          ></c-preview-file-thumbnail-card>
        </template>
      </template>
    </ul>
  </div>
</template>


PreviewFileThumbnails.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
import { LightningElement, wire, api, track } from "lwc";
import { refreshApex } from "@salesforce/apex";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import getFileVersions from "@salesforce/apex/FileController.getVersionFiles";
export default class PreviewFileThumbnails extends LightningElement { loaded = false; @track fileList; @api recordId; @track files = []; get acceptedFormats() { return [".pdf", ".png", ".jpg", ".jpeg"]; } @wire(getFileVersions, { recordId: "$recordId" }) fileResponse(value) { this.wiredActivities = value; const { data, error } = value; this.fileList = ""; this.files = []; if (data) { this.fileList = data; for (let i = 0; i < this.fileList.length; i++) { let file = { Id: this.fileList[i].Id, Title: this.fileList[i].Title, Extension: this.fileList[i].FileExtension, ContentDocumentId: this.fileList[i].ContentDocumentId, ContentDocument: this.fileList[i].ContentDocument, CreatedDate: this.fileList[i].CreatedDate, thumbnailFileCard: "/sfc/servlet.shepherd/version/renditionDownload?rendition=THUMB720BY480&versionId=" + this.fileList[i].Id + "&operationContext=CHATTER&contentId=" + this.fileList[i].ContentDocumentId }; this.files.push(file); } this.loaded = true; } else if (error) { this.dispatchEvent( new ShowToastEvent({ title: "Error loading Files", message: error.body.message, variant: "error" }) ); } } handleUploadFinished(event) { const uploadedFiles = event.detail.files; refreshApex(this.wiredActivities); this.dispatchEvent( new ShowToastEvent({ title: "Success!", message: uploadedFiles.length + " Files Uploaded Successfully.", variant: "success" }) ); } }


PreviewFileThumbnailCard.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
47
48
49
50
51
52
53
54
55
56
57
<template>
  <template if:true={file}>
    <li
      class="
        slds-col
        slds-var-p-vertical_x-small
        slds-small-size_1-of-2
        slds-medium-size_1-of-4
        slds-large-size_1-of-6
      "
    >
      <div class="slds-file slds-file_card slds-has-title" style="width: 14rem">
        <figure>
          <a class="slds-file__crop slds-file__crop_4-by-3 slds-m-top_x-small">
            <img src={thumbnail} alt={file.title} />
          </a>
          <figcaption class="slds-file__title slds-file__title_card">
            <div class="slds-media slds-media_small slds-media_center">
              <lightning-icon
                icon-name={iconName}
                alternative-text={file.Title}
                title={file.Title}
                size="xx-small"
              >
                <span class="slds-assistive-text"
                  >{file.Title}.{file.Extension}</span
                >
              </lightning-icon>
              <div class="slds-media__body slds-var-p-left_xx-small">
                <span class="slds-file__text slds-truncate" title={file.Title}
                  >{file.Title}.{file.Extension}</span
                >
              </div>
            </div>
          </figcaption>
        </figure>

        <div class="slds-is-absolute" style="top: 3px; right: 5px; z-index: 10">
          <lightning-button-menu
            alternative-text="Show File Menu"
            variant="border-filled"
            icon-size="xx-small"
          >
            <lightning-menu-item
              value="preview"
              label="Preview"
            ></lightning-menu-item>
            <lightning-menu-item
              value="delete"
              label="Delete"
            ></lightning-menu-item>
          </lightning-button-menu>
        </div>
      </div>
    </li>
  </template>
</template>


PreviewFileThumbnailCard.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
import { LightningElement, api } from "lwc";

export default class PreviewFileThumbnailCard extends LightningElement {
  @api file;
  @api recordId;
  @api thumbnail;

  get iconName() {
    if (this.file.Extension) {
      if (this.file.Extension === "pdf") {
        return "doctype:pdf";
      }
      if (this.file.Extension === "ppt") {
        return "doctype:ppt";
      }
      if (this.file.Extension === "xls") {
        return "doctype:excel";
      }
      if (this.file.Extension === "csv") {
        return "doctype:csv";
      }
      if (this.file.Extension === "txt") {
        return "doctype:txt";
      }
      if (this.file.Extension === "xml") {
        return "doctype:xml";
      }
      if (this.file.Extension === "doc") {
        return "doctype:word";
      }
      if (this.file.Extension === "zip") {
        return "doctype:zip";
      }
      if (this.file.Extension === "rtf") {
        return "doctype:rtf";
      }
      if (this.file.Extension === "psd") {
        return "doctype:psd";
      }
      if (this.file.Extension === "html") {
        return "doctype:html";
      }
      if (this.file.Extension === "gdoc") {
        return "doctype:gdoc";
      }
    }
    return "doctype:image";
  }
}


FileController.cls

 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
public with sharing class FileController{
@AuraEnabled(cacheable=true)
    public static List<ContentVersion> getVersionFiles(String recordId){
        try {
            return [
		SELECT
		Id,
                Title,
                ContentDocumentId,
                FileType, 
		ContentSize,
		FileExtension,
		VersionNumber,
		CreatedDate,
		VersionData,
                FirstPublishLocationId
		FROM ContentVersion
		WHERE FirstPublishLocationId =:recordId
			ORDER BY CreatedDate DESC
		];
        
        } catch (Exception e) {
            throw new AuraHandledException(e.getMessage());
        }
    }
}


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 :)

Post a Comment

22 Comments

  1. Hey buddy,

    Great Stuff. Thanks for the detailed demo as well.

    Just FYI:

    In previewFileThumbnails.js , you are looking for AccountController in the code but have named the controller class as FileController.


    Also, i have a requirement to navigate between the images with left and right arrow ( A carousel kind of thing), how can i achieve that?

    ReplyDelete
    Replies
    1. Hey,

      Glad you like it. Yes in my demo it's AccountController but while creating this blog I feel that this could create some confusion so that's why I renamed it and removed additional methods as well.

      To navigate images you may use SLDS carousel
      https://developer.salesforce.com/docs/component-library/bundle/lightning-carousel/example

      Delete
    2. Updated the controller, thanks !

      Delete
  2. Will this also work on Community portal ?

    ReplyDelete
    Replies
    1. The thumbnail path could be different in the community portal. I would suggest you to check that first.

      Delete
  3. Hey Kapil,

    how can i preview on click of the image ? Like in aura component clicking on image ( eye icon displayed when hovering over the image) previews the image.

    Is it possible ?

    ReplyDelete
    Replies
    1. Yes you can do that. I am posting a video on it by this saturday on my channel https://youtube.com/salesforcebolt

      Delete
    2. Hey Kapil,

      can you please point me in a direction for now, i need to create this feature today?

      Delete
    3. i am unable to capture the ContentDocumentID on the image click. e.target.dataset.id is coming out to be null. Any suggestions ?

      Delete
    4. Rohan,

      You can create a view url as well like the download one and bind it in a canvas or iframe.

      Delete
    5. Please check your SOQL if you are getting the value there and then try to print it in log as well.

      Delete
  4. I see that you have wired your apex method as a function but it is slightly different. Any specific reason? And how do you get that static url for thumbnail. In the video you have mentioned only about possible values for rendition

    ReplyDelete
    Replies
    1. Hi, no I don't have any specific reason to bind it like this so you may use the standard way as well. For the URL, so that's a common URL address for images you may notice it while open an image attachment in salesforce then check the inspect elements to get the child nodes.

      Delete
  5. hi
    yes i add the componet but after upload the file the preview option was not showing .so how can i do that ??help me on that

    ReplyDelete
    Replies
    1. Are you able to see the popup ? If yes then could you check the URL value in console logs and make sure it's correct.

      Delete
  6. Hey man, Great stuff thank you..
    I'm having a issue in which I can upload the files but the Thumbnails aren't showing underneath. the files are defiantly there but just no preview available.

    checking in console i'm getting "DevTools failed to load source map: Could not parse content for" "Unexpected end of JSON input" could that be something to do with it?

    Cheers mate any help would be much appreciated.

    ReplyDelete
    Replies
    1. I tried it on a different playground and it worked fine so it must be something to do with this specific org.

      Delete
    2. But i get the same message in console in the page that works... so i cant quite figure out what's wrong

      Delete
    3. Thanks, glad you like the post !

      Please try to print JSON in a log first and see if it's in a correct format. Please check below article for reference :
      https://stackoverflow.com/questions/51118396/uncaught-syntaxerror-unexpected-end-of-json-input-at-json-parse-anonymous

      Delete
  7. Hi Kapil Its Great blog such a great blog but i am struggling at one point could help me i written a code but what my requirement is if the file extention is pdf it wan to show pdf image in dattable all the files i am showing datatable now i want to show pdf image is it possible

    ReplyDelete
  8. Hi Kapil, thanks a lot for sharing this knowledge. It is extremely useful.
    I have a question, this will file preview work for files sent by email to a case or it will work only for files uploaded via the custom Upload button?
    Thanks

    ReplyDelete
    Replies
    1. Another question, the little dropdown with 'Preview' and 'Delete' cannot be clicked on after adding the modal. When I click on the little arrow, the modal opens up but not the dropdown. Do you have a solution to this please?
      Thanks

      Delete