使用HttpClient实现文件的上传下载方法
1HTTP
HTTP协议可能是现在Internet上使用得最多、最重要的协议了,越来越多的Java应用程序需要直接通过HTTP协议来访问网络资源。
虽然在JDK的java.net包中已经提供了访问HTTP协议的基本功能,但是对于大部分应用程序来说,JDK库本身提供的功能还不够丰富和灵活。HttpClient用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。
一般的情况下我们都是使用Chrome或者其他浏览器来访问一个WEB服务器,用来浏览页面查看信息或者提交一些数据、文件上传下载等等。所访问的这些页面有的仅仅是一些普通的页面,有的需要用户登录后方可使用,或者需要认证以及是一些通过加密方式传输,例如HTTPS。目前我们使用的浏览器处理这些情况都不会构成问题。但是一旦我们有需求不通过浏览器来访问服务器的资源呢?那该怎么办呢?
下面以本地客户端发起文件的上传、下载为例做个小Demo。HttpClient有两种形式,一种是org.apache.http下的,一种是org.apache.commons.httpclient.HttpClient。
2文件上传
文件上传可以使用两种方式实现,一种是PostMethod方式,一种是HttpPost方式。两者的处理大同小异。PostMethod是使用FileBody将文件包装流包装起来,HttpPost是使用FilePart将文件流包装起来。在传递文件流给服务端的时候,都可以同时传递其他的参数。
2.1客户端处理
2.1.1PostMethod方式
将文件封装到FilePart中,放入Part数组,同时,其他参数可以放入StringPart中,这里没有写,只是单纯的将参数以setParameter的方式进行设置。此处的HttpClient是org.apache.commons.httpclient.HttpClient。
publicvoidupload(StringlocalFile){ Filefile=newFile(localFile); PostMethodfilePost=newPostMethod(URL_STR); HttpClientclient=newHttpClient(); try{ //通过以下方法可以模拟页面参数提交 filePost.setParameter("userName",userName); filePost.setParameter("passwd",passwd); Part[]parts={newFilePart(file.getName(),file)}; filePost.setRequestEntity(newMultipartRequestEntity(parts,filePost.getParams())); client.getHttpConnectionManager().getParams().setConnectionTimeout(5000); intstatus=client.executeMethod(filePost); if(status==HttpStatus.SC_OK){ System.out.println("上传成功"); }else{ System.out.println("上传失败"); } }catch(Exceptionex){ ex.printStackTrace(); }finally{ filePost.releaseConnection(); } }
记得搞完之后,要通过releaseConnection释放连接。
2.1.2HttpPost方式
这种方式,与上面类似,只不过变成了FileBody。上面的Part数组在这里对应HttpEntity。此处的HttpClient是org.apache.http.client.methods下的。
publicvoidupload(StringlocalFile){ CloseableHttpClienthttpClient=null; CloseableHttpResponseresponse=null; try{ httpClient=HttpClients.createDefault(); //把一个普通参数和文件上传给下面这个地址是一个servlet HttpPosthttpPost=newHttpPost(URL_STR); //把文件转换成流对象FileBody FileBodybin=newFileBody(newFile(localFile)); StringBodyuserName=newStringBody("Scott",ContentType.create( "text/plain",Consts.UTF_8)); StringBodypassword=newStringBody("123456",ContentType.create( "text/plain",Consts.UTF_8)); HttpEntityreqEntity=MultipartEntityBuilder.create() //相当于<inputtype="file"name="file"/> .addPart("file",bin) //相当于<inputtype="text"name="userName"value=userName> .addPart("userName",userName) .addPart("pass",password) .build(); httpPost.setEntity(reqEntity); //发起请求并返回请求的响应 response=httpClient.execute(httpPost); System.out.println("Theresponsevalueoftoken:"+response.getFirstHeader("token")); //获取响应对象 HttpEntityresEntity=response.getEntity(); if(resEntity!=null){ //打印响应长度 System.out.println("Responsecontentlength:"+resEntity.getContentLength()); //打印响应内容 System.out.println(EntityUtils.toString(resEntity,Charset.forName("UTF-8"))); } //销毁 EntityUtils.consume(resEntity); }catch(Exceptione){ e.printStackTrace(); }finally{ try{ if(response!=null){ response.close(); } }catch(IOExceptione){ e.printStackTrace(); } try{ if(httpClient!=null){ httpClient.close(); } }catch(IOExceptione){ e.printStackTrace(); } } }
2.2服务端处理
无论客户端是哪种上传方式,服务端的处理都是一样的。在通过HttpServletRequest获得参数之后,把得到的Item进行分类,分为普通的表单和File表单。
通过ServletFileUpload可以设置上传文件的大小及编码格式等。
总之,服务端的处理是把得到的参数当做HTML表单进行处理的。
publicvoidprocessUpload(HttpServletRequestrequest,HttpServletResponseresponse){ FileuploadFile=newFile(uploadPath); if(!uploadFile.exists()){ uploadFile.mkdirs(); } System.out.println("Comeon,baby......."); request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); //检测是不是存在上传文件 booleanisMultipart=ServletFileUpload.isMultipartContent(request); if(isMultipart){ DiskFileItemFactoryfactory=newDiskFileItemFactory(); //指定在内存中缓存数据大小,单位为byte,这里设为1Mb factory.setSizeThreshold(1024*1024); //设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录 factory.setRepository(newFile("D:\\temp")); //Createanewfileuploadhandler ServletFileUploadupload=newServletFileUpload(factory); //指定单个上传文件的最大尺寸,单位:字节,这里设为50Mb upload.setFileSizeMax(50*1024*1024); //指定一次上传多个文件的总尺寸,单位:字节,这里设为50Mb upload.setSizeMax(50*1024*1024); upload.setHeaderEncoding("UTF-8"); List<FileItem>items=null; try{ //解析request请求 items=upload.parseRequest(request); }catch(FileUploadExceptione){ e.printStackTrace(); } if(items!=null){ //解析表单项目 Iterator<FileItem>iter=items.iterator(); while(iter.hasNext()){ FileItemitem=iter.next(); //如果是普通表单属性 if(item.isFormField()){ //相当于input的name属性<inputtype="text"name="content"> Stringname=item.getFieldName(); //input的value属性 Stringvalue=item.getString(); System.out.println("属性:"+name+"属性值:"+value); } //如果是上传文件 else{ //属性名 StringfieldName=item.getFieldName(); //上传文件路径 StringfileName=item.getName(); fileName=fileName.substring(fileName.lastIndexOf("/")+1);//获得上传文件的文件名 try{ item.write(newFile(uploadPath,fileName)); }catch(Exceptione){ e.printStackTrace(); } } } } } response.addHeader("token","hello"); }
服务端在处理之后,可以在Header中设置返回给客户端的简单信息。如果返回客户端是一个流的话,流的大小必须提前设置!
response.setContentLength((int)file.length());
3文件下载
文件的下载可以使用HttpClient的GetMethod实现,还可以使用HttpGet方式、原始的HttpURLConnection方式。
3.1客户端处理
3.1.1GetMethod方式
此处的HttpClient是org.apache.commons.httpclient.HttpClient。
publicvoiddownLoad(StringremoteFileName,StringlocalFileName){ HttpClientclient=newHttpClient(); GetMethodget=null; FileOutputStreamoutput=null; try{ get=newGetMethod(URL_STR); get.setRequestHeader("userName",userName); get.setRequestHeader("passwd",passwd); get.setRequestHeader("fileName",remoteFileName); inti=client.executeMethod(get); if(SUCCESS==i){ System.out.println("Theresponsevalueoftoken:"+get.getResponseHeader("token")); FilestoreFile=newFile(localFileName); output=newFileOutputStream(storeFile); //得到网络资源的字节数组,并写入文件 output.write(get.getResponseBody()); }else{ System.out.println("DownLoadfileoccursexception,theerrorcodeis:"+i); } }catch(Exceptione){ e.printStackTrace(); }finally{ try{ if(output!=null){ output.close(); } }catch(IOExceptione){ e.printStackTrace(); } get.releaseConnection(); client.getHttpConnectionManager().closeIdleConnections(0); } }
3.1.2HttpGet方式
此处的HttpClient是org.apache.http.client.methods下的。
publicvoiddownLoad(StringremoteFileName,StringlocalFileName){ DefaultHttpClienthttpClient=newDefaultHttpClient(); OutputStreamout=null; InputStreamin=null; try{ HttpGethttpGet=newHttpGet(URL_STR); httpGet.addHeader("userName",userName); httpGet.addHeader("passwd",passwd); httpGet.addHeader("fileName",remoteFileName); HttpResponsehttpResponse=httpClient.execute(httpGet); HttpEntityentity=httpResponse.getEntity(); in=entity.getContent(); longlength=entity.getContentLength(); if(length<=0){ System.out.println("下载文件不存在!"); return; } System.out.println("Theresponsevalueoftoken:"+httpResponse.getFirstHeader("token")); Filefile=newFile(localFileName); if(!file.exists()){ file.createNewFile(); } out=newFileOutputStream(file); byte[]buffer=newbyte[4096]; intreadLength=0; while((readLength=in.read(buffer))>0){ byte[]bytes=newbyte[readLength]; System.arraycopy(buffer,0,bytes,0,readLength); out.write(bytes); } out.flush(); }catch(IOExceptione){ e.printStackTrace(); }catch(Exceptione){ e.printStackTrace(); }finally{ try{ if(in!=null){ in.close(); } }catch(IOExceptione){ e.printStackTrace(); } try{ if(out!=null){ out.close(); } }catch(IOExceptione){ e.printStackTrace(); } } }
3.1.3HttpURLConnection方式
publicvoiddownload3(StringremoteFileName,StringlocalFileName){ FileOutputStreamout=null; InputStreamin=null; try{ URLurl=newURL(URL_STR); URLConnectionurlConnection=url.openConnection(); HttpURLConnectionhttpURLConnection=(HttpURLConnection)urlConnection; //true--willsettingparameters httpURLConnection.setDoOutput(true); //true--willallowreadinfrom httpURLConnection.setDoInput(true); //willnotusecaches httpURLConnection.setUseCaches(false); //settingserialized httpURLConnection.setRequestProperty("Content-type","application/x-java-serialized-object"); //defaultisGET httpURLConnection.setRequestMethod("POST"); httpURLConnection.setRequestProperty("connection","Keep-Alive"); httpURLConnection.setRequestProperty("Charsert","UTF-8"); //1min httpURLConnection.setConnectTimeout(60000); //1min httpURLConnection.setReadTimeout(60000); httpURLConnection.addRequestProperty("userName",userName); httpURLConnection.addRequestProperty("passwd",passwd); httpURLConnection.addRequestProperty("fileName",remoteFileName); //connecttoserver(tcp) httpURLConnection.connect(); in=httpURLConnection.getInputStream();//sendrequestto //server Filefile=newFile(localFileName); if(!file.exists()){ file.createNewFile(); } out=newFileOutputStream(file); byte[]buffer=newbyte[4096]; intreadLength=0; while((readLength=in.read(buffer))>0){ byte[]bytes=newbyte[readLength]; System.arraycopy(buffer,0,bytes,0,readLength); out.write(bytes); } out.flush(); }catch(Exceptione){ e.printStackTrace(); }finally{ try{ if(in!=null){ in.close(); } }catch(IOExceptione){ e.printStackTrace(); } try{ if(out!=null){ out.close(); } }catch(IOExceptione){ e.printStackTrace(); } } }
3.2服务端处理
尽管客户端的处理方式不同,但是服务端是一样的。
publicvoidprocessDownload(HttpServletRequestrequest,HttpServletResponseresponse){ intBUFFER_SIZE=4096; InputStreamin=null; OutputStreamout=null; System.out.println("Comeon,baby......."); try{ request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("application/octet-stream"); StringuserName=request.getHeader("userName"); Stringpasswd=request.getHeader("passwd"); StringfileName=request.getHeader("fileName"); System.out.println("userName:"+userName); System.out.println("passwd:"+passwd); System.out.println("fileName:"+fileName); //可以根据传递来的userName和passwd做进一步处理,比如验证请求是否合法等 Filefile=newFile(downloadPath+"\\"+fileName); response.setContentLength((int)file.length()); response.setHeader("Accept-Ranges","bytes"); intreadLength=0; in=newBufferedInputStream(newFileInputStream(file),BUFFER_SIZE); out=newBufferedOutputStream(response.getOutputStream()); byte[]buffer=newbyte[BUFFER_SIZE]; while((readLength=in.read(buffer))>0){ byte[]bytes=newbyte[readLength]; System.arraycopy(buffer,0,bytes,0,readLength); out.write(bytes); } out.flush(); response.addHeader("token","hello1"); }catch(Exceptione){ e.printStackTrace(); response.addHeader("token","hello2"); }finally{ if(in!=null){ try{ in.close(); }catch(IOExceptione){ } } if(out!=null){ try{ out.close(); }catch(IOExceptione){ } } } }
4小结
HttpClient最基本的功能就是执行Http方法。一个Http方法的执行涉及到一个或者多个Http请求/Http响应的交互,通常这个过程都会自动被HttpClient处理,对用户透明。用户只需要提供Http请求对象,HttpClient就会将http请求发送给目标服务器,并且接收服务器的响应,如果http请求执行不成功,httpclient就会抛出异常。所以在写代码的时候注意finally的处理。
所有的Http请求都有一个请求列(requestline),包括方法名、请求的URI和Http版本号。HttpClient支持HTTP/1.1这个版本定义的所有Http方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。上面的上传用到了Post,下载是Get。
目前来说,使用org.apache.commons.httpclient.HttpClient多一些。看自己了~
以上就是小编为大家带来的使用HttpClient实现文件的上传下载方法全部内容了,希望大家多多支持毛票票~