如何解析HTTP POST上传文件请求报文

问题描述

客户端HTTPPOST上传文件报文如下,服务端需要获得文件流,然后写入文件(保持文件原来的格式),这个文件流如何解析获得?有什么好的方法吗?下面是上传一个pdf文件的信息。POST/upload.jspHTTP/1.1Accept:*/*Accept-Language:zh-cnContent-Type:multipart/form-data;boundary=---------------------------7da29f2d890386Host:abc.comContent-Length:1516663Connection:Keep-AliveCache-Control:no-cache-----------------------------7da29f2d890386Content-Disposition:form-data;name="ServerPath"localhost-----------------------------7da29f2d890386Content-Disposition:form-data;name="id"12323123-----------------------------7da29f2d890386Content-Disposition:form-data;name="FileData";filename="D:set.pdf"Content-Type:application/pdf%PDF-1.6%����10obj<</Type/Page/Contents20R/Parent30R/Resources40R/CropBox[00595.22842]/MediaBox[00595.22842]/Rotate0>>endobj40obj<</ColorSpace<</Cs650R>>/ExtGState<</GS160R>>/ProcSet[/PDF/Text]/Font<</F170R/F380R/TT390R/F2100R>>>>endobj20obj<</Filter/FlateDecode/Length1887>>stream-----------------------------7da29f2d890386--

解决方案

本帖最后由 wudeaaa 于 2010-11-11 16:11:51 编辑
解决方案二:
看RFC文档吧:
解决方案三:
request.getInputStream()获取输入流,然后转成文件输入流,用read方法读取就可以了啊。
解决方案四:
引用1楼houjin_cn的回复:

看RFC文档吧:http://www.faqs.org/rfcs/rfc1867.html

文档看过来,里面没有说怎么接收(可能是我没看到?),就是根据表rfc1867的规范上传的,服务端接收时,怎么解析得到文件流,我的方法是首先找到分隔符boundary,然后每次读1024个字节,byte[]srcb=newbyte[1024];Stringcontent="";while(in.read(srcb)!=-1){for(inti=0,j=0;i<srcb.length-1&&j<=i;i++){if(srcb[i]==13&&srcb[i+1]==10){//表示rn的ascii码,说明是一行byte[]sub=subBytes(srcb,j,i);//每一行(从j到i)字节数组Stringline=newString(sub,"UTF-8");//分析...if(line是正文)content+=line;()}然后把content转为byte[],再写入文件中,但是文件格式错误、}}
解决方案五:
这种是标准的上传文件格式啦,用smartupload或者commons-fileupload就可以解释了,根本不需要自己做
解决方案六:
引用4楼chdw的回复:

这种是标准的上传文件格式啦,用smartupload或者commons-fileupload就可以解释了,根本不需要自己做

这两个都是实现文件上传的?我想问的是怎么解析并保存上传的文件
解决方案七:
用组建啊~~
解决方案八:
这两个就是用来解析从IE上传的文件用的。它们都支持将上传的文件保存到你指定的位置
解决方案九:
哥们你问题解决了没?我也正在搞这个问题,
解决方案十:
引用8楼id19870510的回复:

哥们你问题解决了没?我也正在搞这个问题,

我用分段上传的,每接收一段后,就与已接收的合并,以追加的形式写入文件,当完成接收最后一段时完成接收。
解决方案十一:
没必要手工处理,手工处理的话如果你不熟知RFC关于HTTP协议的规范,是做不出来的。处理文件上传的开源框架有很多,比如:ApacheCommons的FileUpload、O'Reilly的COS等等。
解决方案十二:
该回复于2010-12-14 14:35:20被版主删除
解决方案十三:
引用9楼wudeaaa的回复:

引用8楼id19870510的回复:哥们你问题解决了没?我也正在搞这个问题,我用分段上传的,每接收一段后,就与已接收的合并,以追加的形式写入文件,当完成接收最后一段时完成接收。

可否把实现方式分享一下?
解决方案十四:
该回复于2010-12-14 17:59:02被版主删除
解决方案十五:
引用12楼id19870510的回复:

引用9楼wudeaaa的回复:引用8楼id19870510的回复:哥们你问题解决了没?我也正在搞这个问题,我用分段上传的,每接收一段后,就与已接收的合并,以追加的形式写入文件,当完成接收最后一段时完成接收。可否把实现方式分享一下?

privatebyte[]parse(HttpServletRequestrequest)throwsIOException{finalintNONE=0;finalintDATAHEADER=1;finalintFILEDATA=2;finalintFIELDDATA=3;finalintMXA_SEGSIZE=1000*1024*10;//每批最大的数据量10MStringcontentType=request.getContentType();//请求消息类型Stringfieldname="";//表单域的名称Stringfieldvalue="";//表单域的值Stringfilename="";//文件名Stringboundary="";//分界符Stringlastboundary="";//结束符StringfilePath="";Hashtable<String,String>formfields=newHashtable<String,String>();intfilesize=0;//文件长度intpos=contentType.indexOf("boundary=");if(pos!=-1){//取得分界符和结束符pos+="boundary=".length();boundary="--"+contentType.substring(pos);lastboundary=boundary+"--";}intstate=NONE;//得到数据输入流reqbufDataInputStreamin=newDataInputStream(request.getInputStream());//将请求消息的实体送到b变量中inttotalBytes=request.getContentLength();Stringmessage="";if(totalBytes>MXA_SEGSIZE){//每批大于10m时message="Eachbatchofdatacannotbelargerthan"+MXA_SEGSIZE/(1000*1024)+"M";returnnull;}byte[]b=newbyte[totalBytes];in.readFully(b);in.close();StringreqContent=newString(b,"UTF-8");//BufferedReaderreqbuf=newBufferedReader(newStringReader(reqContent));booleanflag=true;inti=0;while(flag==true){Strings=reqbuf.readLine();if((s==null)||(s.equals(lastboundary)))break;switch(state){caseNONE:if(s.startsWith(boundary)){state=DATAHEADER;i+=1;}break;caseDATAHEADER:pos=s.indexOf("filename=");if(pos==-1){//将表单域的名字解析出来pos=s.indexOf("name=");pos+="name=".length()+1;s=s.substring(pos);intl=s.length();s=s.substring(0,l-1);fieldname=s;state=FIELDDATA;}else{//将文件名解析出来Stringtemp=s;pos=s.indexOf("filename=");pos+="filename=".length()+1;s=s.substring(pos);intl=s.length();s=s.substring(0,l-1);//去掉最后那个引号”filePath=s;pos=s.lastIndexOf("\");s=s.substring(pos+1);filename=s;//从字节数组中取出文件数组pos=byteIndexOf(b,temp,0);b=subBytes(b,pos+temp.getBytes().length+2,b.length);//去掉前面的部分intn=0;/***过滤boundary下形如Content-Disposition:form-data;name="bin";*filename="12.pdf"Content-Type:application/octet-stream*Content-Transfer-Encoding:binary的字符串*/while((s=reqbuf.readLine())!=null){if(n==1)break;if(s.equals(""))n++;b=subBytes(b,s.getBytes().length+2,b.length);}pos=byteIndexOf(b,boundary,0);if(pos!=-1)b=subBytes(b,0,pos-1);filesize=b.length-1;formfields.put("filesize",String.valueOf(filesize));state=FILEDATA;}break;caseFIELDDATA:s=reqbuf.readLine();fieldvalue=s;formfields.put(fieldname,fieldvalue);state=NONE;break;caseFILEDATA:while((!s.startsWith(boundary))&&(!s.startsWith(lastboundary))){s=reqbuf.readLine();if(s.startsWith(boundary)){state=DATAHEADER;break;}}break;}}returnb;}//字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似publicstaticintbyteIndexOf(byte[]b,Strings,intstart){returnbyteIndexOf(b,s.getBytes(),start);}//字节数组中的INDEXOF函数,与STRING类中的INDEXOF类似publicstaticintbyteIndexOf(byte[]b,byte[]s,intstart){inti;if(s.length==0){return0;}intmax=b.length-s.length;if(max<0)return-1;if(start>max)return-1;if(start<0)start=0;search:for(i=start;i<=max;i++){if(b[i]==s[0]){intk=1;while(k<s.length){if(b[k+i]!=s[k]){continuesearch;}k++;}returni;}}return-1;}//用于从一个字节数组中提取一个字节数组publicstaticbyte[]subBytes(byte[]b,intfrom,intend){byte[]result=newbyte[end-from];System.arraycopy(b,from,result,0,end-from);returnresult;}//用于从一个字节数组中提取一个字符串publicstaticStringsubBytesString(byte[]b,intfrom,intend){returnnewString(subBytes(b,from,end));}

主要实现是parse,返回的是这段的字节数组。比较繁琐
解决方案:
引用14楼wudeaaa的回复:

引用12楼id19870510的回复:引用9楼wudeaaa的回复:引用8楼id19870510的回复:哥们你问题解决了没?我也正在搞这个问题,我用分段上传的,每接收一段后,就与已接收的合并,以追加的形式写入文件,当完成接收最后一段时完成接收。可否把实现方式分享一下?Javacodeprivatebyte[]……

谢了哥们,我研究一番。。。
解决方案:
publicStringgetResponseXml(Stringurl){StringresponseXML=null;try{MultiThreadedHttpConnectionManagerconnectionManager=newMultiThreadedHttpConnectionManager();HttpClienthttpClient=newHttpClient(connectionManager);log.debug("请求地址:"+url());PostMethodpostMethod=newPostMethod(url);/***将内容放入postMethod中***/postMethod.setRequestBody("请求内容放入到该位置");log.debug("开始接收业务处理反馈报文.n");/***执行postMethod,并获取状态码*/intstatusCode=httpClient.executeMethod(postMethod);log.debug("http返回码:"+statusCode);if(statusCode!=200){//判断是否调用成功log.error("调用失败,请确认地址是否正确");}/**获取反馈内容*/responseXML=postMethod.getResponseBodyAsString();log.debug("反馈报文为:n"+responseXML+"n");/**连接释放*/postMethod.releaseConnection();}catch(HttpExceptione){log.error("HttpException异常,正在重试...");e.printStackTrace();}catch(IOExceptione){log.error("IOException异常,正在重试...n");e.printStackTrace();}returnresponseXML;}
解决方案:
/**获取反馈内容*/responseXML=postMethod.getResponseBodyAsString();InputStreamis=postMethod.getResponseBodyAsStream();byte[]out=postMethod.getResponseBody();其中根据自己需要保存反馈内容,哥好多年没来csdn了,今天忽然有兴趣,来逛逛,^_^。

时间: 2024-08-20 18:24:24

如何解析HTTP POST上传文件请求报文的相关文章

iis6和iis7限制上传文件(请求头)大小以及不支持FSO解决方法_win服务器

解决办法: 一.IIS6 (2003操作系统) 2003 自带的IIS6.0默认限制上传大小限制为200K,下载限制为4M,因此出现上面的问题,解决如下: 1.先打开Internet 信息服务(IIS)管理器 (本地计算机 )---- 属性 ----允许直接编辑配置数据库(N) 一定要勾先"允许直接编辑配置数据库(N)" 2.然后在服务里关闭iis admin service服务,可用命令:iisreset/stop 3.找到windows\system32\inesrv\下的base

php中curl实现GET和POST请求抓取网页或上传文件

一:curl 函数和参数详解 函数库: 1:curl_init 初始化一个curl会话 2:curl_close 关闭一个curl会话 3:curl_setopt 为一个curl设置会话参数 4:curl_error 返回一个包含当前会话错误信息的字符串 5:curl_exec 执行一个curl会话 6:curl_multi_add_handle 向curl批处理会话中添加单独的curl句柄资源 7:curl_multi_close 关闭一个批处理句柄资源 8:curl_multi_exec 解

httpclient通过POST来上传文件,而不是通过流的形式,并在服务端进行解析(通过httpmime.jar来操作)

1. 首先需要对应的JAR包 导入 httpmime-4.1.1.jar. package url; import io.IoStreamUtil; import java.io.File; import java.io.IOException; import java.io.InputStream; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.cli

Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件(二)

Android 发送HTTP GET POST 请求以及通过 MultipartEntityBuilder 上传文件第二版 上次粗略的写了相同功能的代码,这次整理修复了之前的一些BUG,结构也大量修改过了,现在应用更加方便点 http://blog.csdn.net/zhouzme/article/details/18940279 直接上代码了: ZHttpRequset.java package com.ai9475.util; import org.apache.http.HttpEntit

获取参数-struts2在上传文件时获得请求参数的问题

问题描述 struts2在上传文件时获得请求参数的问题 在struts2中可以通过 Map map = ActionContext.getContext().getParameters(); 来获得表单中的数据信息,但当提交的表单格式为enctype="multipart/form-data",即在上传文件时通过上面的方式却得不到数据,在不在对应action中声明文件字段的情况下,如何获得struts2已经封装好了的文件及其他字段信息. 在struts2中确实会自动用common-fi

通过Ajax方式上传文件使用FormData进行Ajax请求_AJAX相关

通过传统的form表单提交的方式上传文件: Html代码  <form id= "uploadForm" action= "http://localhost:8080/cfJAX_RS/rest/file/upload" method= "post" enctype ="multipart/form-data"> <h1 >测试通过Rest接口上传文件 </h1> <p >指定文

【java】利用servlet解析报文,上传文件

由于工作需要,需要做一个excel导入的功能,这就需要上传excel文件到服务器,服务器做逻辑判断此文件是否是excel文件,接着利用poi的api就可以将内容转化为利用jdbc插入到数据库,达到批量数据导入的功能. 废话不多说,这其中上传文件有两种实现方式,一种是直接接到输入流,解析这个输入流,将里面的报文数据剔除,将剩下的文件写入到文件流,放到服务器上,这个是很早之前的解决思路,我们已经很少使用了,它不停的在操作数组,但是网上研究这个输入流的文章不多,写下来,没准对有兴趣的童鞋来说也是一件好

PHP响应post请求上传文件的方法_php技巧

本文实例讲述了PHP响应post请求上传文件的方法.分享给大家供大家参考,具体如下: function send_file($url, $post = '', $file = '') { $eol = "\r\n"; $mime_boundary = md5 ( time () ); $data = ''; $confirmation = ''; date_default_timezone_set ( "Asia/Shanghai" ); $time = date

通过Ajax方式上传文件使用FormData进行Ajax请求

通过传统的form表单提交的方式上传文件: Html代码 <form id= "uploadForm" action= "http://localhost:8080/cfJAX_RS/rest/file/upload" method= "post" enctype ="multipart/form-data"> <h1 >测试通过Rest接口上传文件 </h1> <p >指定文件