一、文件上传
文件包括了office、图片、文本文件等,数据库设计如下:
其中filePath为上传到服务器的路径
前端:
<el-upload
ref="upload"
:headers="headers"
:auto-upload="false"
:on-success="fileUploadSuccess"
:on-error="fileUploadError"
:disabled="importBtnDisabled"
:limit="3"
:action="BASE_API+'/contract/file/uploads'"
name="file"
accept=".*">
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
<el-button
style="margin-left: 10px;"
size="mini"
type="success"
@click="submitUpload">上传文件</el-button>
<el-button
icon="el-icon-delete"
@click="handleDelete"
type="danger"
size="mini"
>删除</el-button
>
</el-upload>
这里使用的是elementUI的上传组件,headers是设置该上传请求携带token操作,不然会报错500,在data中定义:
这里的getToken是request.js中定义的:
on-success和on-error是各种回调函数,根据需要设置,
action是提交地址,BASE_API同样需要在data中定义,process.env是使用config中的prod.env.js中的BASE_API
accept设置为".*"表明默认接收的文件类型,.doc、.pdf啥的,这里默认所有
前端到此就处理完了
后端:
controller层:首先地址对应的是前端中的action,
传入的参数为MultipartFile 类型,首先定义了文件保存路径:
取配置文件值:
计划是按天数创建文件夹,9月20号上传的文件放在服务器的C:/xxxx/upload_file/2022-9-20文件夹下,然后把文件记录保存在文件表中:
@Override
public boolean uploadFiles(MultipartFile file) {
HashMap<String, String> message = new HashMap<>();
if (!file.isEmpty()) {
try {
// 文件保存路径
String today= DateUtil.today();
String filePath = filepath + "/" +today+"/"+ file.getOriginalFilename();
if (!new File(filePath).exists()){
new File(filePath).mkdirs();
}
// 转存文件
file.transferTo(new File(filePath));
message.put("status", filePath);
Files files=new Files();
User user = userService.getCurrentUser();
files.setUploadMan(user.getNickname());
files.setFileName(file.getOriginalFilename());
files.setFilePath(filepath+today);
files.setUploadTime(new Date());
this.save(files);
} catch (Exception e) {
// e.printStackTrace();
message.put("status", "error");
}
}
return true;
}
选取文件,上传:
成功上传到硬盘目录:
二:文件下载
前端:
下载按钮绑定下载事件,传入当前选中文件的id和文件名:
定义方法:
downFile(id,fileName){
downloadFile(id).then((res=>{
console.log(res);
const data = res;
let url = window.URL.createObjectURL(new Blob([data]));
let link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
}));
}
定义downloadFile并引入,注意返回值responseType: ‘blob’:
export function downloadFile(id) {
return request({
url: '/contract/file/downloads?id='+id,
method: 'post',
responseType: 'blob'
})
}
需要注意的是,这个用的是vue的模板这里需要改动:
后台接口返回值为void,这里拦截器拦截,没有res.code,会直接报错如下图,不会下载,这里我把它改成,等于500才报错,成功避免
后端:
controller:需要注意的是,这里返回值最好定义为void
service:首先通过文件id,查询文件表,获得文件所在服务器的路径、文件名,拼接URI为filePath,传入File,得到文件对象,设置类型为application/octet-stream
public void downloadFiles2(String fileId, HttpServletResponse response) throws Exception {
Files files = this.getById(fileId);
String path = files.getFilePath();
String fileName = files.getFileName();
String filePath=path+"/"+fileName;
File file=new File(filePath);
response.reset();
response.setContentType("application/octet-stream");
response.setCharacterEncoding("utf-8");
response.setHeader(
"Content-disposition",
"attachment; filename="+fileName);
try(
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
// 输出流
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
){
byte[] buff = new byte[1024];
int len = 0;
while ((len = bis.read(buff)) > 0) {
bos.write(buff, 0, len);
}
}
}
测试,成功弹出下载页面: