1. 什么是MultipartFile?
MultipartFile是spring用来处理文件封装的一个接口,继承自InputStreamSource,而InputStreamSource接口中封装了getInputStream方法,所以这也是为什么MultipartFile能处理文件流的原因。
2. MultipartFile有哪些方法
方法名称 | 描述 |
---|---|
String getName() | 获取的是前后端约定的传入文件的参数的名称 |
String getOriginalFileName() | 获取的是文件的完整名称,包括文件名称+文件拓展名 |
String getContentType() | 获取的是文件的类型,注意是文件的类型,不是文件的拓展名 |
boolean isEmpty() | 用来判断传入的文件是否为空,如果为空则表示没有传入任何文件 |
long getSize() | 获取文件的大小,单位是字节 |
byte[] getBytes() | 将文件转换成一种字节数组的方式进行传输,会抛出IOException异常 |
InputStream getInputStream() | 将文件转换成输入流的形式来传输文件,会抛出IOException异常 |
void transferTo(File dest) | 将接收文件传输到给定目标路径 |
3. MultipartFile相关spring参数配置
涉及到文件上传和下载,免不了要进行服务关于文件上传的大小限制的配置,如果涉及到nginx的转发,也注意要进行相关参数的配置,否则可能导致调用接口失败,其中,spring针对MultipartFile的配置基本如下:
spring:
servlet:
multipart:
max-file-size: 100MB # 单个数据大小限制
max-request-size: 100MB # 单次总上传数据大小
4. HTTP封装发送MultipartFile
-
文件转MultipartFile
引入maven依赖
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
/**
* file转MultipartFile
*
* @param file 本地文件路径
* @return
*/
public static MultipartFile fileToMultipartFile(File file) {
FileItem fileItem = createFileItem(file);
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
return multipartFile;
}
private static FileItem createFileItem(File file) {
FileItemFactory factory = new DiskFileItemFactory(16, null);
FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
int bytesRead = 0;
byte[] buffer = new byte[8192];
try {
FileInputStream fis = new FileInputStream(file);
OutputStream os = item.getOutputStream();
while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
return item;
}
- 封装HTTP请求返回DTO对象
@Data
@AllArgsConstructor
public class HttpResultDTO {
/**
* 返回的状态码
*/
private int status;
/**
* 返回的数据信息
*/
private String body;
/**
* 返回的头信息
*/
private Map<String, String> header;
}
- 封装HTTP请求
/**
* 发送multipartFile
*
* @param url 请求路径
* @param file MultipartFile流
* @param fileParamName controller对应的接收名称
* @param headerParams 追加的请求头信息
* @param otherParams 其他请求参数
* @return
*/
public static HttpResultDTO postMultipartFile(String url, MultipartFile file, String fileParamName,
Map<String, String> headerParams,
Map<String, String> otherParams) {
CloseableHttpClient httpClient = HttpClients.createDefault();
try {
String fileName = file.getOriginalFilename();
HttpPost httpPost = new HttpPost(url);
//添加header
if (headerParams != null) {
for (Map.Entry<String, String> e : headerParams.entrySet()) {
httpPost.addHeader(e.getKey(), e.getValue());
}
}
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setCharset(Charset.forName("utf-8"));
//加上此行代码解决返回中文乱码问题
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//文件流处理
builder.addBinaryBody(fileParamName, file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);
if (otherParams != null) {
for (Map.Entry<String, String> e : otherParams.entrySet()) {
//追加其他请求参数信息
builder.addTextBody(e.getKey(), e.getValue());
}
}
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
//执行提交
HttpResponse response = httpClient.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
StatusLine statusLine = response.getStatusLine();
int status = statusLine.getStatusCode();
Header[] headers = response.getAllHeaders();
String body = EntityUtils.toString(responseEntity);
Map<String, String> headerMap = Maps.newHashMap();
if (ArrayUtils.isNotEmpty(headers)) {
for (Header header : headers) {
headerMap.put(header.getName(), header.getValue());
}
}
return new HttpResultDTO(status, body, headerMap);
} catch (Exception e) {
//打印日志
LOGGER.error("postMultipartFile error,url:{},ex:{}", url, e.getMessage());
}
return null;
}
5. 接收MultipartFile并处理
/**
* 文件接收处理controller
*
* @param file MultipartFile文件流
* @param accountId 账号id
* @return
*/
@PostMapping("/uploadAudienceFile")
public Response<Boolean> uploadAudienceFile(@RequestParam MultipartFile file,
@RequestParam(required = false) Long accountId,
@RequestParam(required = false) Long audienceId,
@RequestParam(required = false) String userIdType) throws IOException {
//入参强校验
Preconditions.checkArgument(accountId != null, "广告账号为空");
//文件流的封装
String fileName = file.getOriginalFilename();
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder
.create();
multipartEntityBuilder.addBinaryBody("file", file.getInputStream(),
ContentType.MULTIPART_FORM_DATA, fileName);
multipartEntityBuilder.addTextBody("filename", fileName);
//请求参数的封装
multipartEntityBuilder.addTextBody("account_id", String.valueOf(accountId));
multipartEntityBuilder.addTextBody("audience_id", String.valueOf(audienceId));
multipartEntityBuilder.addTextBody("user_id_type", userIdType);
//todo 后续的业务逻辑
return Response.success(true);
}
6. 设置接收和传递文件的最大值
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB