Salesforce LWC學習(二十七) File Upload

本篇參考:html

https://developer.salesforce.com/docs/component-library/bundle/lightning-file-upload/documentationapi

https://developer.salesforce.com/docs/component-library/bundle/lightning-input/specification數組

在salesforce中,上傳附件是一個常常作的操做,在標準的功能基礎上,lwc天然也封裝了自定義的實現。咱們有上傳文檔需求的時候,一般有如下的幾點需求和考慮:this

  • 是否支持多文件上傳
  • 是否支持大文件上傳
  • 是否能夠限制上傳文件的類型
  • 是否能夠對文件進行解析(目前demo中僅限csv)

根據上述的幾點需求和考慮,本篇採用兩種方式來實現文件上傳操做來契合這些要求。url

一. lightning-file-upload實現大文件上傳spa

使用此種方式的優缺點:debug

優勢:3d

  • 支持大文件上傳;
  • 能夠限制上傳文件類型;
  • 支持多文件上傳;

缺點:code

  • 不支持文件解析。

demo以下:component

fileUploadSample.html:上面的連接中給出了 lightning-file-upload的使用方法,經過設置 label展現上傳組件的label名稱,record-id用來指定當前上傳的這些文件將做爲 note & Attachment綁定在哪條數據下,accept指定了限制的格式, uploadfinished是組件自身封裝的事件,用於上傳完成以後執行的事件,multiple設置 true/false來指定當前的組件是否支持多個文件上傳。

<template>
    <lightning-card title="File Upload">
        <lightning-file-upload
            label="上傳附件"
            name="fileUploader"
            accept={acceptedFormats}
            record-id={recordId}
            onuploadfinished={handleUploadFinishedEvent}
            multiple>
    </lightning-file-upload>
    </lightning-card>
</template>

fileUploadSample.js:方法用來指定當前只接受csv,上傳成功之後toast信息展現相關的上傳文件名稱。

import { LightningElement, api } from 'lwc';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
export default class FileUploadSample extends LightningElement {
    @api recordId;

    get acceptedFormats() {
        return ['.csv'];
    }
    handleUploadFinishedEvent(event) {
        const uploadedFiles = event.detail.files;
        let uploadedFilesName = uploadedFiles.map(element => element.name);
        let uploadedFileNamesStr = uploadedFilesName.join(',');

        this.dispatchEvent(
            new ShowToastEvent({
                title: 'Success',
                message: uploadedFiles.length + ' Files uploaded Successfully: ' + uploadedFileNamesStr,
                variant: 'success',
            }),
        );
    }
}

結果展現:

1. 頁面初始化樣子

 2. 上傳兩個文件的UI效果,點擊done即調用 onuploadfinished這個對應的handler

 3. 展現toast消息

 4. 上傳的文件正常的掛到了 Notes & Attachment上面

 二. lightning-input 實現csv文件上傳以及解析

此種方法優勢

  • 支持上傳文件解析

此種方法缺點

  • 對文件上傳大小有嚴格限制

demo以下:

 FileUploadUsingInputController:用於存儲文件以及對csv內容進行解析,須要注意的是,當前方法只針對單個csv的單個sheet頁進行解析。

public with sharing class FileUploadUsingInputController {
    @AuraEnabled
    public static String saveFile(Id recordId, String fileName, String base64Data) {
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
        Blob contentBlob = EncodingUtil.base64Decode(base64Data);
        String content = bitToString(contentBlob, 'UTF-8');
        content = content.replaceAll('\r\n', '\n');
        content = content.replaceAll('\r', '\n');
        String[] fileLines = content.split('\n');
        System.debug('*** ' + JSON.serialize(fileLines));
        for(Integer i = 1; i < fileLines.size(); i++) {
            //TODO 遍歷操做
            system.debug('execute');
        }

        // inserting file
        ContentVersion cv = new ContentVersion();
        cv.Title = fileName;
        cv.PathOnClient = '/' + fileName;
        cv.FirstPublishLocationId = recordId;
        cv.VersionData = EncodingUtil.base64Decode(base64Data);
        cv.IsMajorVersion = true;
        Insert cv;
        return 'successfully';
    }

    public static String bitToString(Blob input, String inCharset){
        //轉換成16進制
        String hex = EncodingUtil.convertToHex(input);
        //一個String類型兩個字節 32位(bit),則一個String長度應該爲兩個16進制的長度,因此此處向右平移一個單位,即除以2
        //向右平移一個單位在正數狀況下等同於除以2,負數狀況下不等
        //eg 9  00001001  >>1 00000100   結果爲4
        final Integer bytesCount = hex.length() >> 1;
        //聲明String數組,長度爲16進制轉換成字符串的長度
        String[] bytes = new String[bytesCount];
        for(Integer i = 0; i < bytesCount; ++i) {
            //將相鄰兩位的16進制字符串放在一個String中
            bytes[i] =  hex.mid(i << 1, 2);
        }
        //解碼成指定charset的字符串
        return EncodingUtil.urlDecode('%' + String.join(bytes, '%'), inCharset);
    }
}

fileUploadUsingInput.html:展現上傳組件以及button

<template>
    <lightning-card title="File Upload Using Input">
        <lightning-layout multiple-rows="true">
            <lightning-layout-item size="12">
                <lightning-input label="" name="file uploader" onchange={handleFilesChange} type="file" accept={acceptedType}></lightning-input><br/>
                <div class="slds-text-body_small">{fileName}
                </div>
            </lightning-layout-item>
            <lightning-layout-item>
                <lightning-button label={UploadFile} onclick={handleSave} variant="brand"></lightning-button>
            </lightning-layout-item>
        </lightning-layout>
        <template if:true={showLoadingSpinner}>
            <lightning-spinner alternative-text="Uploading now"></lightning-spinner>
        </template>
    </lightning-card>
</template>

fileUploadUsingInput.js:由於用string存儲,因此對文件大小有字節的限制。

import { LightningElement, track, api } from 'lwc';
import saveFile from '@salesforce/apex/FileUploadUsingInputController.saveFile';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';

export default class FileUploadUsingInput extends LightningElement {
    @api recordId;
    @track fileName = '';
    @track UploadFile = 'Upload File';
    @track showLoadingSpinner = false;
    filesUploaded = [];
    file;
    fileContents;
    fileReader;
    content;
    MAX_FILE_SIZE = 1500000;

    get acceptedType() {
        return ['.csv'];
    }

    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.file = this.filesUploaded[0];
            if (this.file.size > this.MAX_FILE_SIZE) {
                window.console.log('文件過大');
                return ;
            }
            this.showLoadingSpinner = true;
            this.fileReader= new FileReader();

            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);
                this.saveToFile();
            });
            this.fileReader.readAsDataURL(this.file);
        }
        else {
            this.fileName = '選擇一個csv文件上傳';
        }
    }


    saveToFile() {
        saveFile({ recordId: this.recordId, fileName: this.file.name, base64Data: encodeURIComponent(this.fileContents)})
        .then(result => {
            this.isTrue = true;
            this.showLoadingSpinner = false;

            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Success!!',
                    message: this.fileName + ' - 上傳成功',
                    variant: 'success',
                }),
            );

        })
        .catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: '上傳失敗',
                    message: error.message,
                    variant: 'error',
                }),
            );
        });
    }
}

結果展現:

1. csv中作如下的數據

2. UI效果

 

 3. debug log中打印出來的內容

4. 格式化之後的效果 ,咱們能夠對數組進行二次操做,經過逗號進行分割就能夠獲取每個cell對應的值,一般咱們獲取數據中的for循環 index爲1,即跳過首行標題行。

 總結:篇中主要講述了關於lwc中文件上傳以及文件解析的簡單操做。第一種方式適合大文件上傳,可自定製化不強但功能強悍。第二種方式能夠對數據在apex端進行相關解析,可是有大小的限制。篇中有錯誤地方歡迎指出,有不懂歡迎留言。

相關文章
相關標籤/搜索