• 使用HttpClient实现文件的上传下载


    1 HTTP

        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.1 PostMethod方式

         将文件封装到FilePart中,放入Part数组,同时,其他参数可以放入StringPart中,这里没有写,只是单纯的将参数以setParameter的方式进行设置。此处的HttpClient是org.apache.commons.httpclient.HttpClient。

     1 public void upload(String localFile){
     2         File file = new File(localFile);
     3         PostMethod filePost = new PostMethod(URL_STR);
     4         HttpClient client = new HttpClient();
     5         
     6         try {
     7             // 通过以下方法可以模拟页面参数提交
     8             filePost.setParameter("userName", userName);
     9             filePost.setParameter("passwd", passwd);
    10 
    11             Part[] parts = { new FilePart(file.getName(), file) };
    12             filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
    13             
    14             client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
    15             
    16             int status = client.executeMethod(filePost);
    17             if (status == HttpStatus.SC_OK) {
    18                 System.out.println("上传成功");
    19             } else {
    20                 System.out.println("上传失败");
    21             }
    22         } catch (Exception ex) {
    23             ex.printStackTrace();
    24         } finally {
    25             filePost.releaseConnection();
    26         }
    27     }

    记得搞完之后,要通过releaseConnection释放连接。 

    2.1.2 HttpPost方式

         这种方式,与上面类似,只不过变成了FileBody。上面的Part数组在这里对应HttpEntity。此处的HttpClient是org.apache.http.client.methods下的。

     1 public void upload(String localFile){
     2         CloseableHttpClient httpClient = null;
     3         CloseableHttpResponse response = null;
     4         try {
     5             httpClient = HttpClients.createDefault();
     6             
     7             // 把一个普通参数和文件上传给下面这个地址 是一个servlet
     8             HttpPost httpPost = new HttpPost(URL_STR);
     9             
    10             // 把文件转换成流对象FileBody
    11             FileBody bin = new FileBody(new File(localFile));
    12 
    13             StringBody userName = new StringBody("Scott", ContentType.create(
    14                     "text/plain", Consts.UTF_8));
    15             StringBody password = new StringBody("123456", ContentType.create(
    16                     "text/plain", Consts.UTF_8));
    17 
    18             HttpEntity reqEntity = MultipartEntityBuilder.create()
    19                     // 相当于<input type="file" name="file"/>
    20                     .addPart("file", bin)
    21                     
    22                     // 相当于<input type="text" name="userName" value=userName>
    23                     .addPart("userName", userName)
    24                     .addPart("pass", password)
    25                     .build();
    26 
    27             httpPost.setEntity(reqEntity);
    28 
    29             // 发起请求 并返回请求的响应
    30             response = httpClient.execute(httpPost);
    31             
    32             System.out.println("The response value of token:" + response.getFirstHeader("token"));
    33                 
    34             // 获取响应对象
    35             HttpEntity resEntity = response.getEntity();
    36             if (resEntity != null) {
    37                 // 打印响应长度
    38                 System.out.println("Response content length: " + resEntity.getContentLength());
    39                 // 打印响应内容
    40                 System.out.println(EntityUtils.toString(resEntity, Charset.forName("UTF-8")));
    41             }
    42             
    43             // 销毁
    44             EntityUtils.consume(resEntity);
    45         }catch (Exception e){
    46             e.printStackTrace();
    47         }finally {
    48             try {
    49                 if(response != null){
    50                     response.close();
    51                 }
    52             } catch (IOException e) {
    53                 e.printStackTrace();
    54             }
    55             
    56             try {
    57                 if(httpClient != null){
    58                     httpClient.close();
    59                 }
    60             } catch (IOException e) {
    61                 e.printStackTrace();
    62             }
    63         }
    64     }

    2.2 服务端处理

         无论客户端是哪种上传方式,服务端的处理都是一样的。在通过HttpServletRequest获得参数之后,把得到的Item进行分类,分为普通的表单和File表单。    

         通过ServletFileUpload 可以设置上传文件的大小及编码格式等。

         总之,服务端的处理是把得到的参数当做HTML表单进行处理的。 

     1 public void processUpload(HttpServletRequest request, HttpServletResponse response){
     2         File uploadFile = new File(uploadPath);
     3         if (!uploadFile.exists()) {
     4             uploadFile.mkdirs();
     5         }
     6 
     7         System.out.println("Come on, baby .......");
     8         
     9         request.setCharacterEncoding("utf-8");  
    10         response.setCharacterEncoding("utf-8");  
    11           
    12         //检测是不是存在上传文件  
    13         boolean isMultipart = ServletFileUpload.isMultipartContent(request);  
    14           
    15         if(isMultipart){  
    16             DiskFileItemFactory factory = new DiskFileItemFactory();  
    17             
    18             //指定在内存中缓存数据大小,单位为byte,这里设为1Mb  
    19             factory.setSizeThreshold(1024*1024);  
    20            
    21             //设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录   
    22             factory.setRepository(new File("D:\temp"));  
    23             
    24             // Create a new file upload handler  
    25             ServletFileUpload upload = new ServletFileUpload(factory);  
    26            
    27             // 指定单个上传文件的最大尺寸,单位:字节,这里设为50Mb    
    28             upload.setFileSizeMax(50 * 1024 * 1024);    
    29             
    30             //指定一次上传多个文件的总尺寸,单位:字节,这里设为50Mb  
    31             upload.setSizeMax(50 * 1024 * 1024);     
    32             upload.setHeaderEncoding("UTF-8");
    33               
    34             List<FileItem> items = null;  
    35               
    36             try {  
    37                 // 解析request请求  
    38                 items = upload.parseRequest(request);  
    39             } catch (FileUploadException e) {  
    40                 e.printStackTrace();  
    41             }  
    42             
    43             if(items!=null){  
    44                 //解析表单项目  
    45                 Iterator<FileItem> iter = items.iterator();  
    46                 while (iter.hasNext()) {  
    47                     FileItem item = iter.next(); 
    48                     
    49                     //如果是普通表单属性  
    50                     if (item.isFormField()) {  
    51                         //相当于input的name属性   <input type="text" name="content">  
    52                         String name = item.getFieldName();
    53                         
    54                         //input的value属性  
    55                         String value = item.getString();
    56                         
    57                         System.out.println("属性:" + name + " 属性值:" + value);  
    58                     }  
    59                     //如果是上传文件  
    60                     else {  
    61                         //属性名  
    62                         String fieldName = item.getFieldName();  
    63                         
    64                         //上传文件路径  
    65                         String fileName = item.getName();  
    66                         fileName = fileName.substring(fileName.lastIndexOf("/") + 1);// 获得上传文件的文件名  
    67                         
    68                         try {  
    69                             item.write(new File(uploadPath, fileName));  
    70                         } catch (Exception e) {  
    71                             e.printStackTrace();  
    72                         }  
    73                     } 
    74                 }  
    75             }  
    76         }  
    77         
    78         response.addHeader("token", "hello");
    79     }

        服务端在处理之后,可以在Header中设置返回给客户端的简单信息。如果返回客户端是一个流的话,流的大小必须提前设置!

        response.setContentLength((int) file.length());

    3 文件下载

         文件的下载可以使用HttpClient的GetMethod实现,还可以使用HttpGet方式、原始的HttpURLConnection方式。

    3.1 客户端处理

     3.1.1 GetMethod方式

        此处的HttpClient是org.apache.commons.httpclient.HttpClient。

     1 public void downLoad(String remoteFileName, String localFileName) {
     2         HttpClient client = new HttpClient();
     3         GetMethod get = null;
     4         FileOutputStream output = null;
     5         
     6         try {
     7             get = new GetMethod(URL_STR);
     8             get.setRequestHeader("userName", userName);
     9             get.setRequestHeader("passwd", passwd);
    10             get.setRequestHeader("fileName", remoteFileName);
    11 
    12             int i = client.executeMethod(get);
    13 
    14             if (SUCCESS == i) {
    15                 System.out.println("The response value of token:" + get.getResponseHeader("token"));
    16 
    17                 File storeFile = new File(localFileName);
    18                 output = new FileOutputStream(storeFile);
    19                 
    20                 // 得到网络资源的字节数组,并写入文件
    21                 output.write(get.getResponseBody());
    22             } else {
    23                 System.out.println("DownLoad file occurs exception, the error code is :" + i);
    24             }
    25         } catch (Exception e) {
    26             e.printStackTrace();
    27         } finally {
    28             try {
    29                 if(output != null){
    30                     output.close();
    31                 }
    32             } catch (IOException e) {
    33                 e.printStackTrace();
    34             }
    35             
    36             get.releaseConnection();
    37             client.getHttpConnectionManager().closeIdleConnections(0);
    38         }
    39     }

    3.1.2 HttpGet方式

        此处的HttpClient是org.apache.http.client.methods下的。

     1 public void downLoad(String remoteFileName, String localFileName) {
     2         DefaultHttpClient httpClient = new DefaultHttpClient();
     3         OutputStream out = null;
     4         InputStream in = null;
     5         
     6         try {
     7             HttpGet httpGet = new HttpGet(URL_STR);
     8 
     9             httpGet.addHeader("userName", userName);
    10             httpGet.addHeader("passwd", passwd);
    11             httpGet.addHeader("fileName", remoteFileName);
    12 
    13             HttpResponse httpResponse = httpClient.execute(httpGet);
    14             HttpEntity entity = httpResponse.getEntity();
    15             in = entity.getContent();
    16 
    17             long length = entity.getContentLength();
    18             if (length <= 0) {
    19                 System.out.println("下载文件不存在!");
    20                 return;
    21             }
    22 
    23             System.out.println("The response value of token:" + httpResponse.getFirstHeader("token"));
    24 
    25             File file = new File(localFileName);
    26             if(!file.exists()){
    27                 file.createNewFile();
    28             }
    29             
    30             out = new FileOutputStream(file);  
    31             byte[] buffer = new byte[4096];
    32             int readLength = 0;
    33             while ((readLength=in.read(buffer)) > 0) {
    34                 byte[] bytes = new byte[readLength];
    35                 System.arraycopy(buffer, 0, bytes, 0, readLength);
    36                 out.write(bytes);
    37             }
    38             
    39             out.flush();
    40             
    41         } catch (IOException e) {
    42             e.printStackTrace();
    43         } catch (Exception e) {
    44             e.printStackTrace();
    45         }finally{
    46             try {
    47                 if(in != null){
    48                     in.close();
    49                 }
    50             } catch (IOException e) {
    51                 e.printStackTrace();
    52             }
    53             
    54             try {
    55                 if(out != null){
    56                     out.close();
    57                 }
    58             } catch (IOException e) {
    59                 e.printStackTrace();
    60             }
    61         }
    62     }

    3.1.3 HttpURLConnection方式

     1 public void download3(String remoteFileName, String localFileName) {
     2         FileOutputStream out = null;
     3         InputStream in = null;
     4         
     5         try{
     6             URL url = new URL(URL_STR);
     7             URLConnection urlConnection = url.openConnection();
     8             HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
     9             
    10             // true -- will setting parameters
    11             httpURLConnection.setDoOutput(true);
    12             // true--will allow read in from
    13             httpURLConnection.setDoInput(true);
    14             // will not use caches
    15             httpURLConnection.setUseCaches(false);
    16             // setting serialized
    17             httpURLConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
    18             // default is GET                        
    19             httpURLConnection.setRequestMethod("POST");
    20             httpURLConnection.setRequestProperty("connection", "Keep-Alive");
    21             httpURLConnection.setRequestProperty("Charsert", "UTF-8");
    22             // 1 min
    23             httpURLConnection.setConnectTimeout(60000);
    24             // 1 min
    25             httpURLConnection.setReadTimeout(60000);
    26 
    27             httpURLConnection.addRequestProperty("userName", userName);
    28             httpURLConnection.addRequestProperty("passwd", passwd);
    29             httpURLConnection.addRequestProperty("fileName", remoteFileName);
    30 
    31             // connect to server (tcp)
    32             httpURLConnection.connect();
    33 
    34             in = httpURLConnection.getInputStream();// send request to
    35                                                                 // server
    36             File file = new File(localFileName);
    37             if(!file.exists()){
    38                 file.createNewFile();
    39             }
    40 
    41             out = new FileOutputStream(file);  
    42             byte[] buffer = new byte[4096];
    43             int readLength = 0;
    44             while ((readLength=in.read(buffer)) > 0) {
    45                 byte[] bytes = new byte[readLength];
    46                 System.arraycopy(buffer, 0, bytes, 0, readLength);
    47                 out.write(bytes);
    48             }
    49             
    50             out.flush();
    51         }catch(Exception e){
    52             e.printStackTrace();
    53         }finally{
    54             try {
    55                 if(in != null){
    56                     in.close();
    57                 }
    58             } catch (IOException e) {
    59                 e.printStackTrace();
    60             }
    61             
    62             try {
    63                 if(out != null){
    64                     out.close();
    65                 }
    66             } catch (IOException e) {
    67                 e.printStackTrace();
    68             }
    69         }
    70     }

    3.2 服务端处理

         尽管客户端的处理方式不同,但是服务端是一样的。

     1 public void processDownload(HttpServletRequest request, HttpServletResponse response){
     2         int BUFFER_SIZE = 4096;
     3         InputStream in = null;
     4         OutputStream out = null;
     5         
     6         System.out.println("Come on, baby .......");
     7         
     8         try{
     9             request.setCharacterEncoding("utf-8");  
    10             response.setCharacterEncoding("utf-8");  
    11             response.setContentType("application/octet-stream");
    12             
    13             String userName = request.getHeader("userName");
    14             String passwd = request.getHeader("passwd");
    15             String fileName = request.getHeader("fileName");
    16             
    17             System.out.println("userName:" + userName);
    18             System.out.println("passwd:" + passwd);
    19             System.out.println("fileName:" + fileName);
    20             
    21             //可以根据传递来的userName和passwd做进一步处理,比如验证请求是否合法等             
    22             File file = new File(downloadPath + "\" + fileName);
    23             response.setContentLength((int) file.length());
    24             response.setHeader("Accept-Ranges", "bytes");
    25             
    26             int readLength = 0;
    27             
    28             in = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);
    29             out = new BufferedOutputStream(response.getOutputStream());
    30             
    31             byte[] buffer = new byte[BUFFER_SIZE];
    32             while ((readLength=in.read(buffer)) > 0) {
    33                 byte[] bytes = new byte[readLength];
    34                 System.arraycopy(buffer, 0, bytes, 0, readLength);
    35                 out.write(bytes);
    36             }
    37             
    38             out.flush();
    39             
    40             response.addHeader("token", "hello 1");
    41              
    42         }catch(Exception e){
    43             e.printStackTrace();
    44              response.addHeader("token", "hello 2");
    45         }finally {
    46             if (in != null) {
    47                 try {
    48                     in.close();
    49                 } catch (IOException e) {
    50                 }
    51             }
    52             if (out != null) {
    53                 try {
    54                     out.close();
    55                 } catch (IOException e) {
    56                 }
    57             }
    58         }
    59     }

     4 小结

        HttpClient最基本的功能就是执行Http方法。一个Http方法的执行涉及到一个或者多个Http请求/Http响应的交互,通常这个过程都会自动被HttpClient处理,对用户透明。用户只需要提供Http请求对象,HttpClient就会将http请求发送给目标服务器,并且接收服务器的响应,如果http请求执行不成功,httpclient就会抛出异常。所以在写代码的时候注意finally的处理。    

        所有的Http请求都有一个请求列(request line),包括方法名、请求的URI和Http版本号。HttpClient支持HTTP/1.1这个版本定义的所有Http方法:GET,HEAD,POST,PUT,DELETE,TRACE和OPTIONS。上面的上传用到了Post,下载是Get。

        目前来说,使用org.apache.commons.httpclient.HttpClient多一些。看自己了~

      转载于:http://www.cnblogs.com/Scott007/p/3817285.html

  • 相关阅读:
    WCF后续之旅(3): WCF Service Mode Layer 的中枢—Dispatcher
    .Net 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等)
    我的WCF之旅(13):创建基于MSMQ的Responsive Service
    .net程序集强名称签名实践
    WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成
    .Net 2.0对文件传输协议(FTP)操作(上传,下载,新建,删除,FTP间传送文件等) 2
    WCF后续之旅(6): 通过WCF Extension实现Context信息的传递
    SilverlightCatchWcfError
    WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成
    WCF后续之旅(4):WCF Extension Point 概览
  • 原文地址:https://www.cnblogs.com/zfy0098/p/5230465.html
Copyright © 2020-2023  润新知