① ② ③④⑤⑥⑦⑧⑨
有以下解决思路
用户点击上传,将图片上传到imgs/temp
目录下
用户点击保存按钮后,将图片由temp
目录移动到正常目录
不点击保存按钮,temp 目录的文件,会按照时间,被自动化脚本自动删除。这样保证临时文件不会任意增长。
Base64
操作JS
函数,将本地文件转换成Base64
格式,传递给后台这种操作不常用,因为这样效率太低,除非特殊情况。
Base64
转文件操作在方案①
中,需要将文件上传到服务器上,为什么这么做呢?
但是方案①
也存在问题:
有没有改进方案:
Base64
进行预览。Base64
转成服务器文件,而不是保存到数据库中,数据库中只保存路径。上传文件遇到的场景有:
设置/权限管理/编辑管理员
店铺/店铺帮助/编辑帮助
例如下面的案例,具体由以下功能:
缩略图
,点击后可以预览大图。itemId
与uploadType
/*** 上传图片文件,这些文件可能是新增上传的,也可能update上传的* @param file* @param itemId* @param uploadType* @return*/@Tag(name="帮助")@Operation(summary = "上传文件")@PostMapping("/uploadFile")@AuthenticationType(type=AuthenticationType.authenticated)public Upload uploadFile(@RequestParam("file") MultipartFile file,@RequestParam Integer itemId, @RequestParam Integer uploadType){String subPath = Global.ATTACH_ARTICLE;// 还有关于文件格式限制、文件大小限制,详见:中配置。Path unixPath= storageService.store(file,subPath,storageService.generateRandomFilename());// 将图片压缩成60*60的图片try {Thumbnails.of(unixPath.toFile()).size(80, 80).toFile(getThumbnailsName(unixPath.toString()));}catch (IOException e){throw new BusinessException("缩略图压缩错误:"+e.toString());}// 得到http可以访问的路径String httpUrlPath = StringUtils.replace(unixPath.toString(),storageService.getImgRootLocation().toString(),"");String httpUrlThumbnailsPath=StringUtils.replace(getThumbnailsName(unixPath.toString()),storageService.getImgRootLocation().toString(),"");// 加上/imgs前缀String fileUrl= storageProperties.getImgDirName()+httpUrlPath;Upload upload=new Upload();upload.setFileName( fileUrl);upload.setFileThumb(storageProperties.getImgDirName()+httpUrlThumbnailsPath);upload.setItemId(itemId);upload.setUploadType(uploadType);upload.setFileSize(file.getSize());uploadService.insertSelective(upload);return upload;}private String getThumbnailsName(String oldName){int splitIndex=oldName.lastIndexOf(".");String first= oldName.substring(0,splitIndex)+":60-60";return first+ oldName.substring(splitIndex,oldName.length());}
// 上传文件import { ImgFallback, getSingleUploadImgProps } from '@/services/Common';import type { UploadEndPros } from '@/services/Common';
核心是定义uploadProps
中的onUploadEnd
上传完毕后的方法,其中para.response
是服务器返回的内容。
这个例子的内容比较复杂,是把服务器返回的图片地址,添加到一个数组中,并刷新页面。
// 上传文件const [uploading, setUploading] = React.useState(false);// 构造上传组件的属性const uploadProps = getSingleUploadImgProps({actionUrl: '/store/help/uploadFile',setUploading,onUploadEnd: (para: UploadEndPros<Store.Upload>) => {if (para.success && para.response) {setUploadArray((values: Store.Upload[]): Store.Upload[] => {// 数组类型的state必须要用函数,才可以更新const newArray: Store.Upload[] = [];for (let i = 0; i < values.length; i += 1) {newArray.push(values[i]);}if (para.response) {newArray.push(para.response);}return newArray;});}},});
这里配置了传递参数与disabled
状态。
<Upload{...uploadProps}// 后台需要的附加参数data={{ itemId, uploadType }}disabled={uploading}><div className={styles.upload}><PlusOutlined /><div className={styles.addText}>上传</div></div></Upload>