`
想起要学好java
  • 浏览: 8144 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

通过springmvc接口请求上传文件

    博客分类:
  • http
 
阅读更多
本文主要介绍如何通过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的编码方式。如下所示:
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) + " 条记录");
}
核心的代码都是一样的。
  • 大小: 23.1 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics