文件上传
所谓文件上传,就是将本地文件(包括但不限于图片、音频、视频等)上传至服务器。
这里做一个简单的示例
前端注意事项及页面如下
1. 表单必须设置enctype="multipart/form-data"
2. 提交方式必须是post,没有设置默认是get请求,会报错
3. 在file 类型的 input里设置的name属性值必须要和controller层接收的参数一致,否则要用 @RequestParam("和input里的name属性值一致")注解,不然会报错。
4. 如果是多文件上传,必须在文件输入框中设置 multiple=”multiple“ 属性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传与下载</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="/files/upload">
<!-- multiple="multiple"(可一次选择多个文件)-->
<input type="file" name="files" multiple="multiple">
<input type="submit" value="提交">
</form>
</body>
</html>
后端部分
1. 在配置文件中设置文件上传的路径,便于后期维护,只需要找配置文件修改即可。我这里是application.yml文件,代码如下。
server:
port: 8080
# 设置文件最终上传路径,后续只有在使用的地方用 @Value("${test/targetPath}") 注解即可
test:
targetPath: "Z:\\testUpload\\"
文件上传代码,主要是以下几个步骤
1. 判断接收的文件是否为空,若为空,可以根据实际情况给出提示。
2. 注入文件上传最终路径,并判断该文件夹是否存在,不存在则创建: mkdirs()。
3. 更换文件名,防止有上传至服务器有同名的文件。
4. 转存文件。
/**
* 文件上传与下载
* */
@Controller
@RequestMapping("/files")
public class FileController {
// 代表上传文件的位置,把路径放在配置文件中便于后期维护
@Value("${test.targetPath}")
private String targetPath;
@PostMapping("/upload")
public void upload(@RequestParam("files") MultipartFile file) {
// 多文件上传
// public void upload(@RequestParam("files") MultipartFile[] file) {
// 1. 判断文件是否上传
if (file.isEmpty()) {
//后续可以根据业务需求自行处理(抛出异常或提示等),这里简单演示
System.out.println("文件为空");
}
// 2. 判断上传的目标目录是否存在,不存在则创建
File f = new File(targetPath);
if (!f.exists()) { // 不存在创建文件夹
f.mkdirs();
}
try {
//3. 更换文件名称,防止文件名重复
String fName = file.getOriginalFilename();
// 得到文件名的后缀(.***)
String suffix = fName.substring(fName.indexOf("."));
String newName = UUID.randomUUID().toString() + suffix;
//4. 把临时文件转储到目标文件夹中,因为程序执行完毕,临时文件就会销毁
file.transferTo(new File(targetPath + newName));
System.out.println("上传成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
至此文件上传功能就完成了。
文件下载
文件下载就是将服务器上的文件以IO流的形式写到本地计算机中。
前端页面就用一个<img />标签显示图片简单做下测试,name后面一串的假设就是服务器上要下载的文件名。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传与下载</title>
</head>
<body>
<img src="/files/download?name=d6a63ffc-76a3-4931-bab8-6a3f90d443c5.JPG" alt="">
</body>
</html>
后端基本步骤
1. 在本地读取文件至程序中,需要定义一个字节输入流。
2. 定义一个字节输出流,将文件显示在浏览器中。
3. 读写文件。
4. 关闭流,先创建的流后关闭。
/**
* 文件上传与下载
* */
@Controller
@RequestMapping("/files")
public class FileController {
// 代表上传文件的位置,把路径放在配置文件中便于后期维护
@Value("${test.targetPath}")
private String targetPath;
@GetMapping("/download")
public void download(String name, HttpServletResponse response) { // name参数用于接收前端传递的文件名
//如果下载的中文乱码,则需要指定编码格式
response.setCharacterEncoding("UTF-8");
// 设置下载后的文件名编码格式
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(传递过来的文件名, "UTF-8"));
// 通过输入流读取文件内容
try {
FileInputStream inputStream = new FileInputStream(new File(targetPath + name));
// 通过输出流,将文件写到浏览器中
ServletOutputStream outputStream = response.getOutputStream();
int len = 0; // 记录每次读取文件的长度
byte[] bytes = new byte[1024]; // 每次读取1kB文件大小
while((len = inputStream.read(bytes)) != -1) { // 读不到数据是返回-1
/* // 最后一次从索引0开始读取,一直到len结束,否则最后一次读取不一定能装满1024个字节,如果没有装满,
// 会造成最后一次读取的数据有上一次的数据没有覆盖*/
outputStream.write(bytes, 0, len);
outputStream.flush(); // 刷新流
}
outputStream.close();
inputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
结果
文件下载后乱码
//如果下载的中文乱码,则需要在读取文件时指定编码格式
response.setCharacterEncoding("UTF-8");// 设置下载后的文件名编码格式
response.setHeader("Content-Disposition", "attrchment;filename=" + URLEncoder.encode(文件名, "UTF-8"));
文件下载打开的两种方式
文件下载后打开有两种打开方式,第一种是在浏览器中打开,另一种是下载到本地计算机中打开。
1. 浏览器打开
浏览器打开是在浏览器中另开一个对话窗口,只需要在 a 链接中添加打开方式 target = "_blank"即可。同时在读取文件前设置文件编码格式。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传与下载</title>
</head>
<body>
<img src="/files/download?name=d6a63ffc-76a3-4931-bab8-6a3f90d443c5.JPG" target="_blank">
</body>
</html>
2. 下载到本地计算机打开
只需要在下载的 a 链接中添加 download 属性即可。需要注意的是,文件名有可能是中文的,因此在读取文件之前需要设置文件编码格式和文件名的编码格式。详情移步至本内容 “文件下载后乱码”章节。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传与下载</title>
</head>
<body>
<img src="/files/download?name=d6a63ffc-76a3-4931-bab8-6a3f90d443c5.JPG" download="">
</body>
</html>