通过springmvc接口请求上传文件

本文主要介绍如何通过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 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 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 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) + ” 条记录”);

}

核心的代码都是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值