Springboot上传文件,
使用 CommonsMultipartResolver 解析
使用 Multipartfile 接收到文件后发现文件变大,且文件打不开,文件损坏
这是因为使用了自定义 CustomHttpServletRequestWrapper 包装类继承了 HttpServletRequestWrapper ,获取request 并读取了inputstream把inputsream转为string。
而文件上传时,inpustream转为string,就会出现解析出错,文件损坏。
解决:克隆inputstream 并保存 byte[] ,读取时 byte[] 转换为 inputstream ,这样可以多次读取inputstream
下面是助手类,克隆inputstream 并保存 byte[]
import java.io.*;
public class FileUtils {
//TODO 克隆Inputstream 转换为byte[]
public static byte[] cloneInputStream(InputStream inputStream){
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > -1){
byteArrayOutputStream.write(buffer,0,len);
}
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
inputStream.close();
return byteArrayOutputStream.toByteArray();
}catch (IOException e){
e.printStackTrace();
}
return null;
}
//TODO 使用byte[] 获取 克隆Inputstream
public static InputStream getInputStream(byte[] bytes){
InputStream inputStreamNew = null;
if(bytes != null){
inputStreamNew = new ByteArrayInputStream(bytes);
}
return inputStreamNew;
}
//TODO 使用byte[] 获取 克隆Inputstream
public static ByteArrayInputStream getByteArrayInputStream(byte[] bytes){
ByteArrayInputStream inputStreamNew = null;
if(bytes != null){
inputStreamNew = new ByteArrayInputStream(bytes);
}
return inputStreamNew;
}
}
下面是自定义 CustomHttpServletRequestWrapper 包装类继承了 HttpServletRequestWrapper
import FileUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
// 保存request body的数据
private String body;
// 保存body byte[]
private byte[] bodyBytes;
// 解析request的inputStream(即body)数据,转成字符串
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
//TODO 克隆 inputstream 到 byte[]
bodyBytes = FileUtils.cloneInputStream(inputStream);
inputStream = FileUtils.getInputStream(bodyBytes);
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
//TODO 使用 byte[] 转换为 getByteArrayInputStream , 这样文件上传时就不会出现文件损坏
final ByteArrayInputStream byteArrayInputStream = FileUtils.getByteArrayInputStream(bodyBytes);
ServletInputStream servletInputStream = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
// 赋值给body字段
public void setBody(String body) {
this.body = body;
}
}