项目中通常会涉及到图片上传以便于各种业务场景,复用率高就会封装为模块进行使用,此文章主要针对前端封装文件做详细介绍。
文件
场景
用户资料、审核资料、文件库等场景。
以下会以图片、PDF文档等类型进行演示。
在代码中其实就是 FromData 对象包含 File 对象~。
前端
此处前端以 Vue + ElementPlus 举例。
Vue 组件中定义 Upload 组件
<template>
<el-upload
multiple
action="#"
class="upload-demo"
:auto-upload="false"
:on-change="change"
>
<el-button type="primary">select file</el-button>
</el-upload>
<template>
后端接收文件格式需为 FormData 对象,将 File 对象 append 至 FormData 对象里,以下只是简单示例,axios url 需替换为自己服务器地址,并且需参考下方修改 headers。
const change = (data) => {
let formData = new FormData();
formData.append('file', data.raw);
axios({
method:"POST",
data:formData,
url: 'http://192.168.0.111:8888/upload/files',
headers:{
'Content-Type':'multipart/form-data',
},
}).then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)
})
}
后端
此处以 Java Spring Boot 为示例。
下方代码过于简单就是普通接收 FormData 对象并设置 File 信息保存至本地指定文件夹。
@PostMapping("files")
@ResponseBody
@TokenCheck
public Result<Object> upload(MultipartFile file) {
System.out.println(file);
if (file.isEmpty()) {
return Result.error("文件上传失败");
}
// 获取文件名
String originalFilename = file.getOriginalFilename();
// 获取文件后缀名
String suffixName = originalFilename.substring(originalFilename.lastIndexOf("."));
// 设置文件上传绝对路径
String filePath = "D:\\java\\workspace\\java-bookstore\\src\\main\\resources\\static\\images\\";
// 获取UUID名称
String fileName = UUidUtil.getUUID() + suffixName;
// 获取上传文件的File对象
File dest = new File(filePath + fileName);
System.out.println(dest);
// 开始上传
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
try {
file.transferTo(dest);
return Result.success("操作成功");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return Result.error("上传失败");
}
在上方代码中,我仅是将前端传入的文件保存至本地了,在平常项目中通常是一个 http / https 路径地址保存至数据库中,下方就以文件上传至 oss 举例。
Oss
前端 > Oss
在前端直接调用 Oss 方法并采用分片形式上传文件。
优点:减少请求服务器压力(无),直接上传至 Oss 省去了后端再去调用 Oss,增加响应速度。
缺点:在前端暴露了 Oss 密钥信息,恶意抓包并请求会导致 Oss 储存被恶意损坏,安全性降低。
结合以上两点,请谨慎考虑选择使用以下哪种方式,因为本人公司自研项目,并不会提供外网客户访问。
以下是我在 Vue 项目中对 Oss 上传进行了封装,包括上传进度条、回调。
import {uuid} from "vue-uuid";
const OSS = require("ali-oss");
const multipartUpload = ( async (file,callback) => {
//阿里云oss配置
let client = new OSS({
region: 'XXX',//根据那你的Bucket地点来填写
accessKeyId: "XXX",
accessKeySecret: "XXX",
bucket: 'XXX',//bucket名字
});
/* uploadFiles 百分比进度 */
const progress = (p) => {
// Object的上传进度。
let name = String(p)
let index = name.indexOf('.')
let r = ''
if(index !== -1){
let ress = name.substr(index + 1,2)
if(ress.length >= 2){
ress[0] == 0 ? r = ress.substr(1,1) : r = ress
}else if(ress.length <= 1){
r = ress + '0'
}else {
r = ress
}
callback(r,{res:{status:0}})
}
};
try {
let fileIndex = file.name.indexOf('.')
let fileType = file.name.substr(fileIndex)
const result = await client.multipartUpload('XXX' + uuid.v1() + fileType, file, {
progress, partSize:10 * 1024 * 1024,
});
if(result.res.status === 200){
result.file = file;
callback(100,result);
}
} catch (e) {
// 捕获超时异常。
if (e.code === 'ConnectionTimeoutError') {
console.log('TimeoutError');
}
}
})
export {
multipartUpload
}
Java > Oss
@RestController
public class FileUploadController {
// 设置OSS相关参数
private static final String endpoint = "your-endpoint"; //根据那你的Bucket地点来填写
private static final String accessKeyId = "your-access-key-id";
private static final String accessKeySecret = "your-access-key-secret";
private static final String bucketName = "your-bucket-name"; // 储存空间名称
@PostMapping("/upload")
public String uploadFileToOSS(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return "文件为空";
}
try {
// 获取文件名
String originalFilename = file.getOriginalFilename();
// 生成唯一文件名
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
// 创建OSSClient实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 上传文件至OSS
// 此处 file.getInputStream 为文件流
PutObjectResult putObjectResult = ossClient.putObject(new PutObjectRequest(bucketName, fileName, file.getInputStream()));
// 关闭OSSClient
ossClient.shutdown();
return putObjectResult.getETag();
} catch (IOException e) {
e.printStackTrace();
return "Upload failed";
}
}
}
以上是将文件上传至 Oss 进行储存,当然你可以在上传成功之后再将文件保持至数据库中。
String httpPath = "http://" + bucketName + "." + endpoint + "/" + fileName;
其中
bucketName
、endpoint
和fileName
分别为你的OSS存储桶名称、OSS服务的访问域名和文件在OSS中的路径(路径及文件名称)。
以上就是前后端上传文件实现方案了。