文件上传Demo
文件上传-本地上传
概述
使用场景
文件上传是程序开发中都会用到的一个需求,一般用来共享资源。比如:
- 添加用户头像,文章封面…
- 富文本编辑(插件文件上传)
原理
用户选择文件发送request
请求,程序将文件通过Java-IO流
复制到服务器即为文件上传
用SpringBoot实现文件上传
1. 实现步骤
01. 搭建SpringBoot工程
- 新建项目
- 配置端口
server:
port: 8888
spring:
freemarker:
suffix: .html
cache: false
02. 准备文件上传的前端页面
- 创建
resources/templates/upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>文件上传</title>
</head>
<body>
<h1 style="text-align: center">文件上传</h1>
<form action="/upload/file" enctype="multipart/form-data" method="post">
<input name="dir" value="bbs">
<input name="file" type="file">
<input type="submit" value="文件上传">
</form>
</body>
</html>
03. 实现文件上传的后端逻辑
- 定义文件上传service:
UploadService
此处需要注意:
mkdirs()
可建立多级文件夹mkdir()
只建立一级文件夹
package com.yue.service;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
/**
* @Author: 夜雨
* Create Date Time: 2022-02-26-21:54
* Update Date Time:
* @Version 1.0
* @Description:
* @see
*/
@Service
public class UploadService {
/**
* @Discription: MultipartFile对象是一个SpringMVC提供的文件上传接收类
* 其底层会自动去与HttpServletRequest request中的request.getInputStream()融合,从而实现文件上传
* 所以:文件上传底层原理就是 request.getInputStream()
* @param multipartFile
* @param dir
* @return java.lang.String
* @Author: 夜雨
* @Date: 2022/3/1 20:55
*/
public String uploadImg(MultipartFile multipartFile,String dir){
File targetFile = new File("G://tmp/"+dir);
try {
if (!targetFile.exists())targetFile.mkdir();
multipartFile.transferTo(targetFile);
return "上传成功";
} catch (IOException e) {
e.printStackTrace();
return "上传失败!";
}
}
}
- 定义文件上传controller:UploadController
package com.yue.controller;
import com.yue.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
/**
* @Author: 夜雨
* Create Date Time: 2022-02-26-21:53
* Update Date Time:
* @Version 1.0
* @Description:
* @see
*/
@Controller
public class UploadController {
@Autowired
private UploadService uploadService;
/**
* @Discription: 文件上传
* @param multipartFile
* @param request
* @return java.lang.String
* @Author: 夜雨
* @Date: 2022/2/28 21:27
*/
@PostMapping("/upload/file")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile multipartFile, HttpServletRequest request){
if (multipartFile.isEmpty()){
return "文件有误!";
}
String dir = request.getParameter("dir");
return uploadService.uploadImg(multipartFile,dir);
}
}
- 测试上传,在后台看到如下:
SpringMVC提供了MultipartFile包装对象,原理如下:
通过MultipartFile 我们很清楚的看到,文件已经被服务器接收。
但是会产生一个临时目录,这个目录是可以去配置
文件上传不会直接上传真正的目录,它一定要经过一个临时目录的中转以后,才会上传到真正的目录。作用:
- 防止上传出现网络断开,或者用户上传直接刷新或者取消。因为如果用户的网络断开或者取消,就造成大量的垃圾文件
- 保证真实目录上传的文件一定是有效的。
- 文件上传的大小:也可以进行配置的
- 文件上传的类型:也是进行配置的
server:
port: 8888
spring:
freemarker:
suffix: .html
cache: false
servlet:
multipart:
enabled: true
#当文件大小达到多少时进行磁盘写入
file-size-threshold: 1KB
#单个文件的最大值(默认1MB)
max-file-size: 50MB
#一次性上传文件的最大值
max-request-size: 800MB
#指定临时目录
location: D://data//temptest
注意配置临时目录的时候需要些两个“/”,因为需要转义
04. 配置静态资源存储服务(指定文件存储目录)
增加日期目录,确定文件存放最终目录
package com.yue.service;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @Author: 夜雨
* Create Date Time: 2022-02-26-21:54
* Update Date Time:
* @Version 1.0
* @Description:
* @see
*/
@Service
public class UploadService<contentType> {
private ArrayList<String> contentTypeList;
/**
* @Discription: MultipartFile对象是一个SpringMVC提供的文件上传接收类
* 其底层会自动去与HttpServletRequest request中的request.getInputStream()融合,从而实现文件上传
* 所以:文件上传底层原理就是 request.getInputStream()
* @param multipartFile
* @param dir
* @return java.lang.String
* @Author: 夜雨
* @Date: 2022/3/1 20:55
*/
public String uploadImg(MultipartFile multipartFile,String dir) {
//1.指定文件上传目录
try {
//1.获取文件名
String realFilename = multipartFile.getOriginalFilename();
//2.截取文件后缀名
String imgSuffix = realFilename.substring(realFilename.lastIndexOf("."));
//3.生成唯一文件名(不能使用中文命名,在网页访问过程中统一英文命名,中文名可能会出现乱码,需要进一步处理)
String newFilename = UUID.randomUUID().toString() + imgSuffix;
//4.生成日期目录
SimpleDateFormat dateFormat = new SimpleDateFormat("yyy/MM/dd");
String dataPath = dateFormat.format(new Date());
//5.指定最终目录
File targetPath = new File("D://tmp/" + dir, dataPath);
if (!targetPath.exists()) targetPath.mkdirs();//不存在目录则创建
//6.指定文件上传后服务器的完整文件名
File targetFileName = new File(targetPath, newFilename);
//7.文件上传
multipartFile.transferTo(targetFileName);
return "上传成功";
} catch (IOException e) {
e.printStackTrace();
return "上传失败!";
}
}
}
限制上传文件的类型(类型隔离)
- 前端实现:
“accept”属性:接收类型
<form action="/upload/file" enctype="multipart/form-data" method="post">
<input name="dir" value="bbs">
<input name="file" type="file" accept="image/png">
<input type="submit" value="文件上传">
</form>
作用:上传文件时自动过滤类型,但是仍可以在前端手动选择所有文件,所以文件类型限制一般在后端实现。
- 后端实现