本文主要介绍如何通过http请求springmvc接口,来实现上传文件到服务器,或者读取文件里的内容,实现一些业务需求。
我们知道,上传文件到服务器,可以通过jsp表单提交到接口。这里介绍的是通过http请求实现上传,不通过前台页面jsp表单。具体用apache.commons包下的httpclient来实现。代码如下:
/**
* 将文件作为参数上传到接口中
* @param url
* @param filepath
* @return
*/
private static String uploadFile(String url, String filepath) {
String result = "";
PostMethod postMethod = new PostMethod(url);
try {
File file = new File(filepath);
// SubFilePart filePart = new SubFilePart("file", file);
FilePart filePart = new FilePart("file", file);
filePart.setCharSet("utf-8");
StringPart stringPart = new StringPart("fileSuffix", ".xlsx");
Part[] parts = {filePart, stringPart};
MultipartRequestEntity requestEntity = new MultipartRequestEntity(parts, postMethod.getParams());
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(50000);
int status = httpClient.executeMethod(postMethod);
if(status == HttpStatus.SC_OK) {
InputStream in = postMethod.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String str = null;
while((str = br.readLine()) != null) {
sb.append(str);
}
br.close();
return sb.toString();
} else {
result = "request fail";
}
} catch (Exception e) {
e.printStackTrace();
result = "requst exception";
} finally {
postMethod.releaseConnection();
}
return result;
}
文件作为参数去请求接口,主要用到MultipartRequestEntity这种类型的请求实体。MultipartRequestEntity里面的参数parts包含FilePart,也可以包含StringPart,其中StringPart的参数可以直接在接口里用request.getParameter()来获取。
还有一个请求实体StringRequestEntity,这个一般用来传递字符参数,就是传一串字符到接口,而没有对应的参数名,字符将以流的形式传递到接口中,在接口里要获取,就必须用流的形式,request.getInputStream()是获取请求中流形式存在的参数,再把流里的字符内容读取出来即可。
上面是请求接口的代码,下面写接口。
/**
* 上传文件,通过接口读取上传过来的文件
* @param request
* @param response
*/
@RequestMapping(value = "uploadFile")
public void uploadFile(HttpServletRequest request, MultipartFile file, HttpServletResponse response) {
String fileSuffix = request.getParameter("fileSuffix");
logger.info("fileSuffix = " + fileSuffix);
String filename = file.getOriginalFilename();
logger.info("filename = " + filename);
FileOutputStream fos = null;
InputStream in = null;
try {
in = file.getInputStream();
File localFile = createLocalFile(filename);
fos = new FileOutputStream(localFile);
byte b[] = new byte[1024];
int len = -1;
while((len = in.read(b)) != -1) {
fos.write(b, 0, len);
}
fos.flush();
response.getWriter().write("读取文件并写入服务器成功^_^");
} catch (IOException e) {
logger.error("uploadFile", e);
} finally {
try {
if(fos != null) {
fos.close();
}
if(in != null) {
in.close();
}
} catch (IOException e) {
logger.error("outstream close error : ", e);
}
}
}
其中参数里的MultipartFile file 就是接收请求接口里的FilePart filePart = new FilePart("file", file);这个FilePart的文件,参数名必须一致(file和"file")。
String fileSuffix = request.getParameter("fileSuffix");是直接读取请求里的StringPart的参数。
取得文件后,后续就是一些简单的读写文件操作了。
private File createLocalFile(String filename) {
String timeStr = DateUtils.format(new Date(), "yyMMddHHmmss");
String filenamePrefix = filename.substring(0, filename.lastIndexOf("."));
String filenameSuffix = filename.substring(filename.lastIndexOf("."));
String filepath = "D:\\file\\excel\\" + filenamePrefix + "_" + timeStr + filenameSuffix;
logger.info("createLocalFile filepath = " + filepath);
File file = new File(filepath);
return file;
}
这里需要注意的是如果上传的文件名是中文的,那String filename = file.getOriginalFilename();这里获取的会是乱码。
看FilePart的源码,发现标题是通过ACSIC码编码的,所以才导致乱码,如下:
如果修改成通过utf-8的编码方式,则不会有乱码,需要重写FilePart的sendDispositionHeader()方法。所以写一个类继承FilePart,再重写sendDispositionHeader()方法,将文件名的编码形式改成EncodingUtil.getBytes(filename, getCharSet())即可,getCharSet()是指FilePart的编码方式。如下所示:
如果修改成通过utf-8的编码方式,则不会有乱码,需要重写FilePart的sendDispositionHeader()方法。所以写一个类继承FilePart,再重写sendDispositionHeader()方法,将文件名的编码形式改成EncodingUtil.getBytes(filename, getCharSet())即可,getCharSet()是指FilePart的编码方式。如下所示:
public class SubFilePart extends FilePart {
private static Logger logger = LoggerFactory.getLogger(SubFilePart.class);
public SubFilePart(String name, File file) throws FileNotFoundException {
super(name, file);
}
@Override
protected void sendDispositionHeader(OutputStream out) throws IOException {
logger.info("sendDispositionHeader SubFilePart 设置文件名重写...");
out.write(CONTENT_DISPOSITION_BYTES);
out.write(QUOTE_BYTES);
out.write(EncodingUtil.getAsciiBytes(getName()));
out.write(QUOTE_BYTES);
String filename = this.getSource().getFileName();
logger.info("sendDispositionHeader filename = " + filename);
if (filename != null) {
out.write(EncodingUtil.getAsciiBytes(FILE_NAME));
out.write(QUOTE_BYTES);
out.write(EncodingUtil.getBytes(filename, getCharSet()));
out.write(QUOTE_BYTES);
}
}
}
然后将之前请求接口的代码FilePart filePart = new FilePart("file", file);改成SubFilePart filePart = new SubFilePart("file", file);即可。
当然有些需求是这样的,上传的文件并不是一定要保存到服务器,有些可能只是需要读取文件里的内容做一些其他的需求。其实没什么改变,只是将保存文件到服务器的部分改成读取文件内容即可。
/**
* 上传文件,通过接口读取上传文件里的内容并存到数据库表中
* @param request
* @param response
*/
@RequestMapping(value = "readFile")
public void readFileAndSave(HttpServletRequest request, MultipartFile file, HttpServletResponse response) {
InputStream in = null;
BufferedReader br = null;
List<TMobile> tMobiles = new ArrayList<>();
int num = 0;
try {
in = file.getInputStream();
br = new BufferedReader(new InputStreamReader(in));
String line = null;
while((line = br.readLine()) != null) {
tMobiles.add(createTMobile(line));
num ++;
if(num == 1000) {
addBatch(tMobiles);
num = 0;
tMobiles = new ArrayList<>();
}
}
if(tMobiles.size() > 0) {
addBatch(tMobiles);
}
response.getWriter().write("读取文件并保存成功^_^");
} catch (IOException e) {
logger.error("uploadFile", e);
} finally {
try {
if(br != null) {
br.close();
}
if(in != null) {
in.close();
}
} catch (IOException e) {
logger.error("uploadFile close stream error : ", e);
}
}
}
private TMobile createTMobile(String mobile) {
TMobile tMobile = new TMobile();
tMobile.setMobile(mobile);
return tMobile;
}
private void addBatch(List<TMobile> tMobiles) {
try {
Integer addBack = tMobileService.addBatch(tMobiles);
logger.info("addBatch 批量插入 " + tMobiles.size() + " 条记录,成功插入 " + addBack + " 条");
if(addBack <= 0) {
add(tMobiles);
}
} catch (Exception e) {
logger.error("addBatch error : ", e);
add(tMobiles);
}
}
private void add(List<TMobile> tMobiles) {
int failNum = 0;
for(TMobile tMobile : tMobiles) {
try {
tMobileService.add(tMobile);
} catch (Exception e) {
failNum ++;
logger.error("add error : ", e);
}
}
logger.info("add 单次插入成功 " + (tMobiles.size() - failNum) + " 条记录");
}
核心的代码都是一样的。
相关推荐
Spring Web MVC是一种基于Java的实现了...支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动...支持本地化(Locale)解析、主题(Theme)解析及文件上传等;
Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC...支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格 式化和数据绑定机制;
DispatcherServlet 设计的,并分发请求到处理程序(handler),Spring MVC支持可配置的处理程序映射(handler mapping),视图解析(view resolution)、 区域设置(locale)和主题解析(theme resolution),以及文件上传等...
用来对用户要求加密上传的文件进行加密计划学习Bootstrap前端框架##截图展示###首页界面#####登录界面###文件列表显示界面##目前已经做好的API接口:方法名接口 请求方式:请求参数返回结果详细描述processLogin/u/...
springmvc前端控制和请求转发、文件上传处理、http消息转换 mysql数据库做数据存储 mybatis做数据访问框架 maven用作项目构建工具 同时还是用了mybatis三剑客 一、 mybatis-generator 是一个mybatis代码生成插件,该...
SpringMVC:用于构建Web层的MVC框架,处理请求映射、视图解析等。 MyBatis:数据持久层框架,简化数据库操作,提供SQL映射和数据库访问。 功能模块: 用户注册与登录:允许用户创建账户并登录系统。 商家管理:...
包含Web应用开发时,用到Spring框架时所需的核心类,包括自动载入WebApplicationContext特性的类、Struts与JSF集成类、文件上传的支持类、Filter类和大量工具辅助类。 18. spring-webmvc-4.1.1.RELEASE.jar 包含...
│ 06.FastDFS安装步骤-文件上传.avi │ 07.配置nginx插件访问图片.avi │ 08.测试图片上传.avi │ 09.FastDFS工具类的使用.avi │ 10.图片上传过程分析.avi │ 11.图片上传Service.avi │ 12.图片上传完成.avi │ ...
它是安全的-通过Java EE web.xml或通过Servlet过滤器(例如Spring-Security) 它是可扩展的-通过简单的类扩展 它是可嵌入的-到您的Java Web应用程序中,使测试应用程序更加容易 我已经看到许多以博客形式在网络上...