问题描述
客户端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了,今天忽然有兴趣,来逛逛,^_^。