Java 文件上传与下载

文件上传与下载

基于Springboot + Vue前后端分离

项目源码:

  • 前端springboot-file
  • 后端springboot-file-process

流程梳理

文件上传

  1. 前端提交文件,后端使用MultipartFile接收

  2. 后端新建File并保存到对应的目录上(此时文件后端服务一般与文件存储放在同一个linux服务器上)

  3. 如果需要回显,存储成功后,向前端返回文件路径。此时该路径必须能够通过http直接访问

    1. 还有一种方法,返回图片的base64格式,放到img标签里面

文件下载

  1. 前端提交文件名到后端

  2. 后端搜索到文件名,通过文件流写入到HttpServletResponseOutputStream

  3. 前端通过window.location接收

    1. 或者是通过以下方式设置图片的Base64,其中imgurl是vue的动态绑定变量

      1
      <img :src="'data:image/png;base64,'+imgurl" alt="">

代码实例

前端代码

upload.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<html>

<head>
<meta charset="UTF-8" />
<title>文件上传页面</title>
</head>

<body>
<div id="fileUploadVue">
<h1 th:inlines="text">文件上传</h1>
<form>
<p>选择文件: <input type="file" name="fileName" ref="file" /></p>
<p><input type="button" value="提交" @click="fileUpload" /></p>
<p><input type="button" value="下载" @click="fileDownload" /></p>
</form>

<h1 th:inlines="text">图片上传并回显</h1>
<form>
<p>选择文件: <input type="file" name="fileName" ref="file" /></p>
<p><input type="button" value="提交" @click="fileUploadAndShow" /></p>
<img :src="'data:image/png;base64,'+imageBase64" alt="" />
</form>
</div>
</body>

<script src="vue/vue.min.js"></script>
<script src="vue/axios.min.js"></script>
<script type="text/javascript">
var fileUploadVue = new Vue({
el: "#fileUploadVue",
data: {
imageBase64: "",
},
mounted() {

},
created() {
var me = this;
me.testPostStatus();
},
methods: {

// 测试前后端是否调通
testPostStatus() {
var name = "hello";
var postTestUrl = "http://localhost:8001/postTest?name="; // 这里必须添加 'http://' 前缀,否则会CORS请求被拦截
axios.post(postTestUrl + name).then(res => {
console.log(res.data);
});
},

fileUpload() {
var formData = new FormData();
var uploadFileUrl = "http://localhost:8001/uploadFile";

formData.append('file', this.$refs.file.files[0]);

axios.post(uploadFileUrl, formData).then(res => {
if (res.data == "SUCCESS") {
alert("文件上传成功");
}
else {
alert("文件上传失败");
}
});
},

fileDownload() {
var downloadFileUrl = "http://localhost:8001/downloadFile";

window.location = "http://localhost:8001/downloadFile";

},

fileUploadAndShow() {
var me = this;
var formData = new FormData();
var downloadFileUrl = "http://localhost:8001/fileUploadAndShow";

formData.append('file', this.$refs.file.files[0]);

axios.post(downloadFileUrl, formData).then(res => {
console.log(res.data);
if (res.data.status == "SUCCESS") {
me.imageBase64 = res.data.imageBase64;
alert("文件上传成功");
}
else {
alert("文件上传失败");
}
});
},
},
});
</script>

</html>

后端代码

SwaggerConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.file.config;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2 {

// http://localhost:8088/swagger-ui.html 原路径
// http://localhost:8088/doc.html 新路径,github开源的swagger页面,自带汉化

// 配置swagger2核心配置 docket
@Bean
public Docket createRestApi() {

Predicate<RequestHandler> filePredicate = RequestHandlerSelectors.basePackage("com.file.controller");

return new Docket(DocumentationType.SWAGGER_2) // 指定api类型为swagger2
.apiInfo(apiInfo()) // 用于定义api文档汇总信息
.select()
.apis(Predicates.or(filePredicate))
.paths(PathSelectors.any()) // 所有controller
.build();
}

private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("sora blog·博客接口api") // 文档页标题
.contact(new Contact("sora",
"https://www.kalosora.work",
"kalosora@gmail.com")) // 联系人信息
.description("sora blog博客的api文档") // 详细信息
.version("1.0.0") // 文档版本号
.termsOfServiceUrl("https://www.kalosora.work") // 网站地址
.build();
}

}




FileController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package com.file.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

// 允许跨域
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST})
@Api(value = "文件处理相关Controller", tags = {"文件处理相关Controller"})
@RestController
public class FileController {

// Status Code
private final String STATUS_SUCCESS = "SUCCESS";
private final String STATUS_ERROR = "ERROR";

@GetMapping("/downloadFile")
@ApiOperation(value = "文件下载的接口", notes = "文件下载的接口", httpMethod = "GET")
public String downloadFile(HttpServletResponse response) throws UnsupportedEncodingException {
String fileName = "布偶.jpg";
String storePath = "/Users/kalosora/Desktop/模拟下载/";

File downLoadFile = new File(storePath + fileName);
if (!downLoadFile.exists()) {
return STATUS_ERROR;
}

// 文件存在,开始下载
response.setHeader("content-type", "application/octet-stream");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));

// 定义输入流
byte[] buffer = new byte[1024];
FileInputStream is = null;
BufferedInputStream bis = null;

OutputStream os = null;

try {
os = response.getOutputStream();
is = new FileInputStream(downLoadFile);
bis = new BufferedInputStream(is);

int i = bis.read(buffer);
while (i != -1) {
os.write(buffer);
i = bis.read(buffer);
}

} catch (IOException e) {
e.printStackTrace();
}

try {
bis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}

return STATUS_SUCCESS;
}

@PostMapping("/uploadFile")
@ApiOperation(value = "文件上传的接口", notes = "文件上传的接口", httpMethod = "POST")
public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {

// 文件保存路径
String storePath = "/Users/kalosora/Desktop/模拟下载/";

if (file.isEmpty()) {
return STATUS_ERROR;
}

// 获取原文件名
String originalFileName = file.getOriginalFilename();
System.out.println("文件名: " + originalFileName);

// 获取文件类型
String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));
System.out.println("文件类型: " + fileType);

// 模拟文件保存到与应用同一个服务器
File saveFile = new File(storePath + originalFileName);
System.out.println("新文件:" + saveFile.toString());
if (!saveFile.exists()) {
file.transferTo(saveFile);
}

return STATUS_SUCCESS;
}

@PostMapping("/fileUploadAndShow")
@ApiOperation(value = "文件上传的接口", notes = "文件上传的接口", httpMethod = "POST")
public Map<String, Object> fileUploadAndShow(@RequestParam("file") MultipartFile file) throws IOException {

Map<String, Object> resultMap = new HashMap<String, Object>();

// 文件保存路径
String storePath = "/Users/kalosora/Desktop/模拟下载/";

if (file.isEmpty()) {
resultMap.put("status", STATUS_ERROR);
return resultMap;
}

// 获取原文件名
String originalFileName = file.getOriginalFilename();
System.out.println("文件名: " + originalFileName);

// 获取文件类型
String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));
System.out.println("文件类型: " + fileType);

// 模拟文件保存到与应用同一个服务器
File saveFile = new File(storePath + originalFileName);
System.out.println("新文件:" + saveFile.toString());
if (!saveFile.exists()) {
file.transferTo(saveFile);
}else
{
// 文件存在,则直接返回图片Base64
String imageBase64 = fileToBase64(saveFile);
resultMap.put("imageBase64", imageBase64);
}

resultMap.put("status", STATUS_SUCCESS);

return resultMap;
}

@PostMapping("/postTest")
@ApiOperation(value = "测试前后端交互的接口", notes = "测试前后端交互的接口", httpMethod = "POST")
public String postTest(@RequestParam("name") String name) {
return STATUS_SUCCESS;
}

/**
* 文件转换成Base64编码
*/
/**
* 文件转换为base64
* @param file
* @return
*/
public String fileToBase64(File file) {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
InputStream in = null;
byte[] fileData = null;
// 读取文件字节数组
try {
in = new FileInputStream(file);
fileData = new byte[in.available()];
in.read(fileData);
in.close();
} catch (IOException e) {
e.printStackTrace();
}

// 对字节数组Base64编码并且返回
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(fileData);
}
}

参考网站

Springboot文件上传下载

0%