解决 request.getInputStream()只能获取一次的问题
程序员文章站
2022-03-10 12:09:36
...
在开发中有时候我们会在filter中获取上传文件然后验证其合法性,但是在filter中获取一次以后,我们在controller想再次获取上传文件对象是获取不到的。request.getInputStream()返回的是ServletInputStream,此方法没有实现流的mark/reset方法,我们在filter中读取以后无法对流进行复位。实现方法,直接贴代码了。
BodyReaderHttpServletRequestWrapper.java
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
try {
body = StreamUtils.getByteByStream(request.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}
}
StreamUtils.java
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class StreamUtils {
public static byte[] getByteByStream(InputStream is) throws Exception {
byte[] buffer=new byte[1024];
int len=0;
ByteArrayOutputStream bos=new ByteArrayOutputStream();
while((len=is.read(buffer))!=-1){
bos.write(buffer,0,len);
}
bos.flush();
return bos.toByteArray();
}
}
UploadFilter.java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class UploadFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) arg0;
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
//测试在filter中获取一次
InputStream is = requestWrapper.getInputStream();
// 读取要下载的文件,保存到文件输入流
// 创建输出流
String tempFileName = "C:/tempFile.jpg";
// 指向临时文件
File tempFile = new File(tempFileName);
// outPutStream输出流指向临时文件
FileOutputStream out = new FileOutputStream(tempFile);
// 创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
// 循环将输入流中的内容读取到缓冲区当中
while ((len = is.read(buffer)) > 0) {
// 输出缓冲区的内容到浏览器,实现文件下载
out.write(buffer, 0, len);
}
// 关闭文件输入流
is.close();
// 关闭输出流
out.close();
chain.doFilter(requestWrapper, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
}
controller里面的方法
/**
* 下载SQL文件
* @param request
* @param model
*/
@RequestMapping(value="/downloadsql",method=RequestMethod.POST)
public void downloadsql(HttpServletRequest request, HttpServletResponse response,Model model){
//测试
try {
InputStream is = request.getInputStream();
// 读取要下载的文件,保存到文件输入流
// 创建输出流
String tempFileName = "C:/tempFile.jpg";
// 指向临时文件
File tempFile = new File(tempFileName);
// outPutStream输出流指向临时文件
FileOutputStream out = new FileOutputStream(tempFile);
// 创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
// 循环将输入流中的内容读取到缓冲区当中
while ((len = is.read(buffer)) > 0) {
// 输出缓冲区的内容到浏览器,实现文件下载
out.write(buffer, 0, len);
}
// 关闭文件输入流
is.close();
// 关闭输出流
out.close();
} catch (Exception e) {
// TODO: handle exception
}
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
if(!ServletFileUpload.isMultipartContent(request)){
return;
}
try {
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
if(!item.isFormField()){
InputStream in = item.getInputStream();
ExcelUtils eu = new ExcelUtils();
StringBuilder sb = new StringBuilder();
eu.readExcel(sb, in);
String sqlContent = sb.toString();
FileManager fm = new FileManager();
Date date = new Date();
String path = request.getSession().getServletContext().getRealPath("/")+File.separator+"resources"+File.separator+"sql"+File.separator;
String fileName = "SQL"+TFun.getFormatDateYMDHMS(date)+".sql";
fm.createDirectory(path);
fm.createFile(path+fileName, sqlContent);
JSONObject result = new JSONObject();
result.put("success", true);
result.put("msg", "");
result.put("filepath", request.getContextPath()+File.separator+"resources"+File.separator+"sql"+File.separator+fileName);
//关闭输出流
item.delete();
JSONService.writeStringIntoResponse(response, result.toJSONString());
}
}
} catch (Exception e) {
JSONObject result = new JSONObject();
result.put("success", false);
result.put("msg", e.getMessage());
result.put("filepath", "");
JSONService.writeStringIntoResponse(response, result.toJSONString());
e.printStackTrace();
}
}
上一篇: request.getInputStream() 只能读一次的解决方法
下一篇: 拦截器中,request中getReader()和getInputStream()只能调用一次,构建可重复读取inputStream的request.
推荐阅读
-
wap网站开发之解决Ajax跨域获取json数组的问题
-
如何解决 PHP 第一次连接Oracle非常慢的问题
-
C#实现微信公众号群发消息(解决一天只能发一次的限制)实例分享
-
浅谈图片上传利用request.getInputStream()获取文件流时遇到的问题
-
解决Android从相册中获取图片出错图片却无法裁剪问题的方法
-
IOS 下获取 rootviewcontroller 的版本不同的问题解决办法
-
解决springboot 获取form-data里的file文件的问题
-
完美解决因数据库一次查询数据量过大导致的内存溢出问题
-
IOS 下获取 rootviewcontroller 的版本不同的问题解决办法
-
完美解决Jpush[获取sdk版本失败!]的问题