文件上传
一.前端文件上传基础代码:
<form
method="post" enctype="multipart/form-data"
action="http://localhost:8080/file/upload"
>
<input name="myFile" type="file">
<input type="submit" value="提交">
</form>
以下部分为固定内容
,不可改变.
1.method="post"
采用post方式提交数据
2.enctype="multipart/form-data"
采用multipart格式上传文件(二进制格式,传输效率最高)
3.type="file"
使用input的file控件上传文件
二.Controller
中使用MultipartFile
类型,即可接收上到上传的文件.
@PostMapping("/file/upload")
public R<String> upload(MultipartFile file) throws UnsupportedEncodingException {
String fileName = this.fileUpload.run(file);
return R.success(fileName);
}
重点: MultipartFile
接收的变量名必须与前端上传控件的name属性
同名.
如:<input name="myFile" type="file">
VSpublic R<String> upload(MultipartFile file)
,此处myFile==myFile
;
PS:MultipartFile
的底层是对spring-web对Apache
中的两个组件commons-fileupload
和commons-io
;
三.专门创建一个类用于处理上传后的文件.将之保存到本地硬盘中.
public class FileUpload {
/**
* 上傳文件
* @param myFile 文件
*/
public String run(MultipartFile myFile) {
//确保我们保存文件的目录存在
this.guaranteeFileDirectory();
//随机生成的文件名
String randomFileName = this.generateRandomFileName(myFile);
try {
//myFile:在本次请求中,它是以临时文件的方式存在于tomcat中,当本次请求结束的时候,该临时文件将被删除.
//将临时文件转存到别的位置,避免被删除.
myFile.transferTo(new File("D:\\uploadfile\\" + randomFileName));
} catch (IOException e) {
e.printStackTrace();
}
return randomFileName;
}
//确保目录存在:判断当前目录是否存在,若不存在,则生成一个目录
private void guaranteeFileDirectory() {
File dir = new File("D:\\uploadfile\\");
if (!dir.exists()) {
//目录不存在,需要创建
dir.mkdir();
}
}
//使用UUID随机生成一个文件名.
private String generateRandomFileName(MultipartFile myFile) {
//原始文件名
String originalFilename = myFile.getOriginalFilename();
//取得文件后缀
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
//在部分真实场景中,文件表中还需要保存文件的类型
//String fileType = myFile.getContentType();
//使用UUID重新生成新的文件名,防止文件名重复造成文件覆盖
String randomFileName = UUID.randomUUID().toString() + suffix;
return randomFileName;
}
}
四.在Controller
中将保存的文件名返回给前端
至此,上传功能已完成.
文件下载
一.前端下载文件表现形式.
1.以附件形式下载,弹出对话框,选择文件保存的位置;
2.直接在浏览器中打开浏览(如:<img src="http://localhost:8080/download/avatar.png" />
);
两种的本质都是服务端将文件以【流】的形式写回浏览器.
二.Controller
中使用HttpServletResponse
的方式将值写回给前端(区别于其他场景直接返回JSON格式数据
).
/**
* 文件下载
*
* @param fileName 文件名
* @param response
*/
@GetMapping("/download/{fileName}")
public void downloadFile(@PathVariable String fileName, HttpServletResponse response) {
this.fileDownload.run(fileName, response);
}
三.专门建一个类处理文件的下载.
public class FileDownload {
/**
* 下載文件
*
* @param name 文件名
* @param response
*/
public void run(String fileName, HttpServletResponse response) {
try {
//指定向浏览器传输的文件类型.
//在实际开发中,在上传的时候,会同时存入文件的类型,在下载的时候,会返回文件的类型
// response.setContentType("image/jpeg");
//从【本地】读取文件,生成流对象
FileInputStream fileInputStream = new FileInputStream(new File("D:\\uploadfile\\" + fileName));
//使用 服务端输出流API(ServletOutputStream) 将流输出到浏览器
ServletOutputStream outputStream = response.getOutputStream();
//使用输入流将文件置入bytes数组,然后再通过response中的输入流将文件返回给前端
int length = 0;
byte[] bytes = new byte[1024];
while (length != -1) {
//从输入流中读取(取出)多个字节数据,如到输入流末尾则返回-1
length = fileInputStream.read(bytes);
// System.out.println("打印出读取到的字节长度length:---->"+length);
//使用API将流写入待发送缓存区
outputStream.write(bytes,0,length);
//手动将缓存中的流数据发送至浏览器(不手动发送,满了也会自动发送,手动发送更稳定)
outputStream.flush();
}
//关闭资源
outputStream.close();
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
四.前端只要传入的文件名,就可以直接通过路径的【GET】请求,取得文件数据.当然,也可以将路径写在<img src="路径"/>
.
完.