zoukankan      html  css  js  c++  java
  • 使用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做进一步处理,比如验证请求是否合法等             
    23             File file = new File(downloadPath + "\" + fileName);
    24             response.setContentLength((int) file.length());
    25             response.setHeader("Accept-Ranges", "bytes");
    26             
    27             int readLength = 0;
    28             
    29             in = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);
    30             out = new BufferedOutputStream(response.getOutputStream());
    31             
    32             byte[] buffer = new byte[BUFFER_SIZE];
    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             response.addHeader("token", "hello 1");
    42              
    43         }catch(Exception e){
    44             e.printStackTrace();
    45              response.addHeader("token", "hello 2");
    46         }finally {
    47             if (in != null) {
    48                 try {
    49                     in.close();
    50                 } catch (IOException e) {
    51                 }
    52             }
    53             if (out != null) {
    54                 try {
    55                     out.close();
    56                 } catch (IOException e) {
    57                 }
    58             }
    59         }
    60     }

     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多一些。看自己了~

    -------------------------------------------------------------------------------

    如果您看了本篇博客,觉得对您有所收获,请点击右下角的 [推荐]

    如果您想转载本博客,请注明出处

    如果您对本文有意见或者建议,欢迎留言

    感谢您的阅读,请关注我的后续博客

  • 相关阅读:
    安装VMtools vim编辑器的使用 压缩包命令 Linux下的用户管理 (第三天)
    VM虚拟机安装 常用Linux命令 网卡配置 (第二天)
    数据库的交互模式 常用的dos命令 (第一天)
    Validate US Telephone Numbers FreeCodeCamp
    Arguments Optional FreeCodeCamp
    Everything Be True FreeCodeCamp
    Binary Agents FreeCodeCamp
    Steamroller FreeCodeCamp
    Drop it FreeCodeCamp
    Smallest Common Multiple FreeCodeCamp
  • 原文地址:https://www.cnblogs.com/Scott007/p/3817285.html
Copyright © 2011-2022 走看看