Salesforce LWC学习(二十七) File Upload
本篇参考:
https://developer.salesforce.com/docs/component-library/bundle/lightning-file-upload/documentation
https://developer.salesforce.com/docs/component-library/bundle/lightning-input/specification
在salesforce中,上传附件是一个经常做的操作,在标准的功能基础上,lwc自然也封装了自定义的实现。我们有上传文档需求的时候,通常有以下的几点需求和考虑:
- 是否支持多文件上传
- 是否支持大文件上传
- 是否可以限制上传文件的类型
- 是否可以对文件进行解析(目前demo中仅限csv)
根据上述的几点需求和考虑,本篇采用两种方式来实现文件上传操作来契合这些要求。
一. lightning-file-upload实现大文件上传
使用此种方式的优缺点:
优点:
- 支持大文件上传;
- 可以限制上传文件类型;
- 支持多文件上传;
缺点:
- 不支持文件解析。
demo如下:
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('rn', '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端进行相关解析,但是有大小的限制。篇中有错误地方欢迎指出,有不懂欢迎留言。
- javascript单线程环境实现真正的setTimeout
- 利用pipework与OVS构建跨主机容器网络
- Docker系列教程07-Dockerfile指令详解
- Docker系列教程06-实战:修改Nginx首页
- prompt() 方法,弹框带输入框
- Docker系列教程05-容器常用命令
- 数据分析利器-NumPy
- 【LEETCODE】模拟面试-134-Gas Station
- Docker系列教程17-默认bridge网络中配置DNS
- Docker系列教程16-network命令
- 【LEETCODE】模拟面试-206. Reverse Linked List
- Eslint检测出的问题如何自动修复
- 【LEETCODE】模拟面试-215. Kth Largest Element in an Array
- Docker系列教程15-Docker容器网络
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- SAP CRM One Order函数CHANGE_OW的设计原理
- 关于checkpoint你可能不知道的事
- SAP CRM One Order函数CRM_Object_FILL_OW的设计原理
- SAP CRM One Order header extension的缓存机制设计原理
- SAP CRM数据库表CRMD_CUMULAT_H的设计原理
- Python从入门到大师一百篇教程 | 前言:Python的前世和发展
- Java和ABAP的垃圾回收机制(Garbage Collection)比较
- Java和SAP ABAP的异常处理
- Java的字节码和ABAP load的比较
- matplotlib | Python强大的作图工具,让你从此驾驭图表(一)
- 使用ES6的fetch API读取数据时要注意的一个和cookie相关的坑
- 跟牛老师一起学WEBGIS——WEBGIS基础(地图切片)
- Go语言 | 并发设计中的同步锁与waitgroup用法
- LeetCode 99 | 如何不用递归遍历二叉搜索树?MT方法给你答案
- 以攻击者角度学习某风控设备指纹产品