java 编写url多个参数_Java使用HTTP编程模拟多参数多文件表单信息的请求与处理...

本文目的是提供Java环境下模拟浏览器页面提交多参数多文件表单请求以及解析请求的Demo代码。这里用Java提供的HttpURLConnection类做HTTP请求,再原始点可以直接使用socket。使用socket的话,通用性会更好点。

首先要了解一个概念,文件和参数一起上传,HTTP请求头中包含了如下格式。

Content-Type: multipart/form-data; boundary=boundarystr

请求体的数据格式也是有一个标准的,具体如下。

HTTP请求头

--boundarystr

Content-Disposition: form-data; name="param1"

param1value

--boundarystr

Content-Disposition: form-data; name="param2"

param2value

--boundarystr

Content-Disposition: form-data; name="param3"; filename="filename1"

Content-Type: application/octet-stream

文件数据

--boundarystr

Content-Disposition: form-data; name="param4"; filename="filename2"

Content-Type: application/octet-stream

文件数据

--boundarystr--

boundary参数一般会取一些类似于UUID这样的值。请求头和请求体之间隔了两个回车,也就是一个"\r\n\r\n"。双横杠boundary和Content-Disposistion描述之间有一个回车("\r\n")。name和filename的参数值需要加双引号。Content描述和数据之间有两个回车("\r\n\r\n")。请求提最后的boundary后尾需要跟上双横杠。例子中,用application/octet-stream通用的描述文件数据内容格式,如果事先知道文件格式,可以根据MIME类型(http://www.w3school.com.cn/media/media_mimeref.asp)填写。好处是解析时候比较方便。

在编写代码时必须严格遵循这个消息格式,包括换行和横杠以及boundary。否则会导致数据无法解析。

下面是一个制作该HTTP消息并进行请求的代码。

/*** 制作多参数多文件消息并进行请求

*@paramurlString 目标url

*@parammutiFileList 含有文件信息的List,最简单的情况是map中包含文件名称和路径,每个map表示一个文件。

*@paramparams 普通参数map,key作为参数名称,value作为参数值

*@return

*/

public String httpUploadMutiFile(String urlString,List> mutiFileList, Mapparams){

String repString= null;

InputStream is= null;

OutputStream out= null;//定义boundarystr

final String BOUNDARYSTR =Long.toHexString(System.currentTimeMillis());//定义回车换行

final String CRLF = "\r\n";final String BOUNDARY = "--"+BOUNDARYSTR+CRLF;

StringBuilder paramsText= newStringBuilder();byte[] paraTextByte;try{//首先制作普通参数信息

if(params != null && params.size() != 0){for(String key:params.keySet()){

paramsText.append(BOUNDARY);

paramsText.append("Content-Disposition: form-data;name=\""+key+"\""+CRLF);

paramsText.append("Content-type: text/plain"+CRLF+CRLF);

paramsText.append(params.get(key));

paramsText.append(CRLF);

}

paraTextByte= paramsText.toString().getBytes("UTF-8");

}else{// paraTextByte = null;

}

}catch(Exception e){

e.printStackTrace();

paraTextByte= null;

}//写入参数部分信息

try{//先制作请求头

URL url = newURL(urlString);

HttpURLConnection con=(HttpURLConnection) url.openConnection();

con.setDoInput(true);

con.setDoOutput(true);

con.setRequestMethod("POST");

con.setRequestProperty("connection", "Keep-Alive");

con.setRequestProperty("Charset", "UTF-8");

con.setRequestProperty("Content-type", "multipart/form-data;boundary=" +BOUNDARYSTR);//获得输出流

out = newDataOutputStream(con.getOutputStream());//写入普通参数部分

if(paraTextByte != null && paraTextByte.length > 0){

out.write(paraTextByte);

}//写入文件信息

MapfileInfoMap;for(int i = 0; i < mutiFileList.size(); i++){

fileInfoMap=mutiFileList.get(i);//当前文件map存有文件名称(uuid型)和文件的中文名称,以及文件的字节数据//如果文件过大,不建议使用该方式,建议传递文件路径再读取写入。

String fileName = (String)fileInfoMap.get("fileName");

String suffix= fileName.substring(fileName.indexOf("."));

String chFileName= fileInfoMap.get("chName")+suffix;

StringBuilder sb= newStringBuilder();

sb.append(BOUNDARY);

sb.append("Content-Disposition: form-data;name=\""+chFileName+"\";filename=\""

+ chFileName + "\""+CRLF);//sb.append("Content-Type:application/octet-stream"+CRLF+CRLF);//文件均是jpg图片类型

sb.append("Content-Type:image/jpg"+CRLF+CRLF);

out.write(sb.toString().getBytes());//写入输出流

byte[] fileData = (byte[])fileInfoMap.get("data");/*** 如果map里存储的是文件路径,那么可以使用FileInputStream读取文件信息,并写入到OutputStream中。

* 具体就不写了。*/out.write(fileData);

out.write(CRLF.getBytes("UTF-8"));

}byte[] foot = ("--" + BOUNDARYSTR + "--"+CRLF).getBytes("UTF-8");//定义最后数据分隔线

out.write(foot);

out.flush();

is=con.getInputStream();

repString=ioTool.getStringFromInputStream(is);

}catch(Exception e){

e.printStackTrace();

logger.error("往业务系统写入文件失败:"+e.getMessage());

}returnrepString;

}

下面是数据的解析。

以SpringMVC配置的HTTP接口为例。但具体的解析写法和Spring没什么关系。

在写这篇博客之前,我尝试使用了ServletFileUpload类和request.getParts()两种方法来解析。前一种的好处是有很多便利的Servlet  API可以使用。但是,HTTP请求体内容只能解析一次。这意味着,在进行解析前我们不能使用以下方法操作request。https://stackoverflow.com/questions/13881272/servletfileuploadparserequestrequest-returns-an-empty-list

request.getParameter();

request.getParameterMap();

request.getParameterNames();

request.getParameterValues();

request.getReader();

request.getInputStream();

感觉不是很灵活。在servlet3.0后,request增加了getPart()和getParts()方法,利用这些方法处理文件数据表单可能要好一些。

@RequestMapping(value = "uploadFile",method =RequestMethod.POST)public voidhandleMutiPartForm(HttpServletRequest request, HttpServletResponse response){//可以使用request.getParameter()获取普通参数数据

String param1 = request.getParameter("param1");

String param2= request.getParameter("param2");//获取parts

Collectionparts;try{

parts=request.getParts();

}catch(IOException ioe){

parts= null;

}catch(ServletException se){

parts= null;

}if(parts != null){//遍历parts//因为所有的参数信息都会在Collection中体现//这里只需要获取文件部分

String saveFilePath = "D://FileUpload/";byte[] bytes = new byte[512];for(Part part:parts){//Content-type: image/* 图片类型数据

if(part.getContentType().startsWith("image")){

String fileName=part.getSubmittedFileName();

String paramName=part.getName();try{

InputStream ins=part.getInputStream();

String filePath= saveFilePath+fileName;

File file= newFile(filePath);if(!file.exists()){

file.createNewFile();

}

FileOutputStream fos= newFileOutputStream(file);while(ins.read(bytes, 0, 512) != -1){

fos.write(bytes);

}

ins.close();

fos.close();

}catch(IOException ioe){

}

}

}

}try{

response.getWriter().write("返回的信息");

}catch(IOException ioe){

}

}

RFC相关介绍:

http://www.faqs.org/rfcs/rfc2388.html

stackoverflow相关问题:

https://stackoverflow.com/questions/2793150/using-java-net-urlconnection-to-fire-and-handle-http-requests/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值