最近在写一个教学平台项目,其中一个需求是教师上传课程资料,然后教师还可以查询自己在某课程中发送的历史资料,并下载查看。其中就涉及到了文件上传、文件下载。
【上传文件】
前端(VUE):
此功能的相关组件用对话框dialog包含:
<el-dialog
title="发送课程资料"
:visible.sync="dialogVisible"
width="50%"
:before-close="handleClose">
<el-upload
class="upload-demo"
ref="upload"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList"
:auto-upload="false"
:limit="1"
:http-request="httpRequest"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
</el-upload>
<el-input
type="textarea"
:rows="2"
placeholder="请输入备注信息"
v-model="note"
style="margin-top: 20px;">
</el-input>
<el-button style="margin-top: 20px" size="small" type="success" @click="submitForm">上传</el-button>
<span slot="footer" class="dialog-footer">
</span>
</el-dialog>
点击上传按钮实现文件上,submitForm()代码如下:
httpRequest(param){
const fileObj = param.file
this.fd.append('material', fileObj)
console.log(this.fd.get('material'));
},
//上传对应的处理
submitForm() {
this.$refs.upload.submit();
this.fd.append('note',this.note)
this.fd.append('classID',this.currentClass)
this.fd.append('courseName',this.currentCourse)
// this.fd['note']= this.note
// this.fd['classID']=this.currentClass
// this.fd['courseName']=this.currentCourse
console.log(this.fd);
service({
url:'/api/teacher/course/sendMaterial',
method:'post',
data:this.fd,
headers: {
"Content-Type":"multipart/form-data"
}
}).then(res => {
this.$message({
message: '发送成功',
type: 'success'
})
})
this.fd=new FormData()
},
可以看到,文件内容、课程ID、课程名和文件备注都以键值对的形式保存在formdata对象fd中,后端需要获取这些字段值。
后端:
public void sendMaterial(CourseMaterial material, HttpServletRequest request) throws IOException {
String realPath = request.getSession().getServletContext().getRealPath("/upload");
File path = new File(realPath);
if (!path.exists()) {
path.mkdir();
}
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartHttpServletRequest.getFile("material");
material.setFilename(file.getOriginalFilename());
String finalPath = realPath+'\\'+file.getOriginalFilename();
if(!file.isEmpty()){
file.transferTo(new File(finalPath));
System.out.println("成功接收一个文件");
}
material.setFilepath(finalPath);
Date currentTime= new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = formatter.format(currentTime);
material.setSendTime(dateString);
courseService.submitCourseMaterial(material);
}
后端以CourseMaterial对象来接收各个字段的值:课程ID、课程名和文件备注。以request对象来获取material字段对应的文件内容,然后通过transferTo方法实现保存用户上传的文件到服务器(本机)。也可以采用另外一种方式,通过MultipartFile数组来接收多个上传的文件的方式的话(就不需要通过HttpServletRequest接口来获取文件内容),还不太清楚如何接收如课程ID、课程名和文件备注这些每个文件对应的信息。
【文件下载】
前端:
downloadFile(filepath){
service({
url:'/api/teacher/course/download',
method:'get',
params:{
filepath:filepath
},
responseType: 'blob'
}).then( res => {
const blob = new Blob([res])
const fileName = 'cbk.pdf'
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName)
}
})
}
downloadFile()为下载按钮对应的点击事件,参数filepath为服务器中保存的文件对应的文件路径。需要注意的是,将请求对应的responseType字段设置为'blob',不然无法下载文件。
后端:
@GetMapping("/download")
public ResponseEntity<byte[]> download(String filepath) throws IOException {
//获取文件对象
byte[] bytes = FileUtils.readFileToByteArray(new File(filepath));
HttpHeaders headers=new HttpHeaders();
headers.set("Content-Disposition","attachment;filename=test2.png");
ResponseEntity<byte[]> entity=new ResponseEntity<>(bytes,headers, HttpStatus.OK);
return entity;
}