热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

下面小编就为大家带来一篇使用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。

 

public void upload(String localFile){
    File file = new File(localFile);
    PostMethod filePost = new PostMethod(URL_STR);
    HttpClient client = new HttpClient();
    
    try {
      // 通过以下方法可以模拟页面参数提交
      filePost.setParameter("userName", userName);
      filePost.setParameter("passwd", passwd);

      Part[] parts = { new FilePart(file.getName(), file) };
      filePost.setRequestEntity(new MultipartRequestEntity(parts, filePost.getParams()));
      
      client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
      
      int status = client.executeMethod(filePost);
      if (status == HttpStatus.SC_OK) {
        System.out.println("上传成功");
      } else {
        System.out.println("上传失败");
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      filePost.releaseConnection();
    }
  }

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

2.1.2 HttpPost方式

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

public void upload(String localFile){
    CloseableHttpClient httpClient = null;
    CloseableHttpResponse respOnse= null;
    try {
      httpClient = HttpClients.createDefault();
      
      // 把一个普通参数和文件上传给下面这个地址 是一个servlet
      HttpPost httpPost = new HttpPost(URL_STR);
      
      // 把文件转换成流对象FileBody
      FileBody bin = new FileBody(new File(localFile));

      StringBody userName = new StringBody("Scott", ContentType.create(
          "text/plain", Consts.UTF_8));
      StringBody password = new StringBody("123456", ContentType.create(
          "text/plain", Consts.UTF_8));

      HttpEntity reqEntity = MultipartEntityBuilder.create()
          // 相当于
          .addPart("file", bin)
          
          // 相当于
          .addPart("userName", userName)
          .addPart("pass", password)
          .build();

      httpPost.setEntity(reqEntity);

      // 发起请求 并返回请求的响应
      respOnse= httpClient.execute(httpPost);
      
      System.out.println("The response value of token:" + response.getFirstHeader("token"));
        
      // 获取响应对象
      HttpEntity resEntity = response.getEntity();
      if (resEntity != null) {
        // 打印响应长度
        System.out.println("Response content length: " + resEntity.getContentLength());
        // 打印响应内容
        System.out.println(EntityUtils.toString(resEntity, Charset.forName("UTF-8")));
      }
      
      // 销毁
      EntityUtils.consume(resEntity);
    }catch (Exception e){
      e.printStackTrace();
    }finally {
      try {
        if(response != null){
          response.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      
      try {
        if(httpClient != null){
          httpClient.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

2.2 服务端处理

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

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

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

public void processUpload(HttpServletRequest request, HttpServletResponse response){
    File uploadFile = new File(uploadPath);
    if (!uploadFile.exists()) {
      uploadFile.mkdirs();
    }

    System.out.println("Come on, baby .......");
    
    request.setCharacterEncoding("utf-8"); 
    response.setCharacterEncoding("utf-8"); 
     
    //检测是不是存在上传文件 
    boolean isMultipart = ServletFileUpload.isMultipartContent(request); 
     
    if(isMultipart){ 
      DiskFileItemFactory factory = new DiskFileItemFactory(); 
      
      //指定在内存中缓存数据大小,单位为byte,这里设为1Mb 
      factory.setSizeThreshold(1024*1024); 
      
      //设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录  
      factory.setRepository(new File("D:\\temp")); 
      
      // Create a new file upload handler 
      ServletFileUpload upload = new ServletFileUpload(factory); 
      
      // 指定单个上传文件的最大尺寸,单位:字节,这里设为50Mb  
      upload.setFileSizeMax(50 * 1024 * 1024);  
      
      //指定一次上传多个文件的总尺寸,单位:字节,这里设为50Mb 
      upload.setSizeMax(50 * 1024 * 1024);   
      upload.setHeaderEncoding("UTF-8");
       
      List items = null; 
       
      try { 
        // 解析request请求 
        items = upload.parseRequest(request); 
      } catch (FileUploadException e) { 
        e.printStackTrace(); 
      } 
      
      if(items!=null){ 
        //解析表单项目 
        Iterator iter = items.iterator(); 
        while (iter.hasNext()) { 
          FileItem item = iter.next(); 
          
          //如果是普通表单属性 
          if (item.isFormField()) { 
            //相当于input的name属性   
            String name = item.getFieldName();
            
            //input的value属性 
            String value = item.getString();
            
            System.out.println("属性:" + name + " 属性值:" + value); 
          } 
          //如果是上传文件 
          else { 
            //属性名 
            String fieldName = item.getFieldName(); 
            
            //上传文件路径 
            String fileName = item.getName(); 
            fileName = fileName.substring(fileName.lastIndexOf("/") + 1);// 获得上传文件的文件名 
            
            try { 
              item.write(new File(uploadPath, fileName)); 
            } catch (Exception e) { 
              e.printStackTrace(); 
            } 
          } 
        } 
      } 
    } 
    
    response.addHeader("token", "hello");
  }

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

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

3 文件下载

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

3.1 客户端处理

3.1.1 GetMethod方式

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

public void downLoad(String remoteFileName, String localFileName) {
    HttpClient client = new HttpClient();
    GetMethod get = null;
    FileOutputStream output = null;
    
    try {
      get = new GetMethod(URL_STR);
      get.setRequestHeader("userName", userName);
      get.setRequestHeader("passwd", passwd);
      get.setRequestHeader("fileName", remoteFileName);

      int i = client.executeMethod(get);

      if (SUCCESS == i) {
        System.out.println("The response value of token:" + get.getResponseHeader("token"));

        File storeFile = new File(localFileName);
        output = new FileOutputStream(storeFile);
        
        // 得到网络资源的字节数组,并写入文件
        output.write(get.getResponseBody());
      } else {
        System.out.println("DownLoad file occurs exception, the error code is :" + i);
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      try {
        if(output != null){
          output.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      
      get.releaseConnection();
      client.getHttpConnectionManager().closeIdleConnections(0);
    }
  }

3.1.2 HttpGet方式

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

public void downLoad(String remoteFileName, String localFileName) {
    DefaultHttpClient httpClient = new DefaultHttpClient();
    OutputStream out = null;
    InputStream in = null;
    
    try {
      HttpGet httpGet = new HttpGet(URL_STR);

      httpGet.addHeader("userName", userName);
      httpGet.addHeader("passwd", passwd);
      httpGet.addHeader("fileName", remoteFileName);

      HttpResponse httpRespOnse= httpClient.execute(httpGet);
      HttpEntity entity = httpResponse.getEntity();
      in = entity.getContent();

      long length = entity.getContentLength();
      if (length <= 0) {
        System.out.println("下载文件不存在!");
        return;
      }

      System.out.println("The response value of token:" + httpResponse.getFirstHeader("token"));

      File file = new File(localFileName);
      if(!file.exists()){
        file.createNewFile();
      }
      
      out = new FileOutputStream(file); 
      byte[] buffer = new byte[4096];
      int readLength = 0;
      while ((readLength=in.read(buffer)) > 0) {
        byte[] bytes = new byte[readLength];
        System.arraycopy(buffer, 0, bytes, 0, readLength);
        out.write(bytes);
      }
      
      out.flush();
      
    } catch (IOException e) {
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }finally{
      try {
        if(in != null){
          in.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      
      try {
        if(out != null){
          out.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

3.1.3 HttpURLConnection方式

public void download3(String remoteFileName, String localFileName) {
    FileOutputStream out = null;
    InputStream in = null;
    
    try{
      URL url = new URL(URL_STR);
      URLConnection urlCOnnection= url.openConnection();
      HttpURLConnection httpURLCOnnection= (HttpURLConnection) urlConnection;
      
      // true -- will setting parameters
      httpURLConnection.setDoOutput(true);
      // true--will allow read in from
      httpURLConnection.setDoInput(true);
      // will not use caches
      httpURLConnection.setUseCaches(false);
      // setting serialized
      httpURLConnection.setRequestProperty("Content-type", "application/x-java-serialized-object");
      // default is GET            
      httpURLConnection.setRequestMethod("POST");
      httpURLConnection.setRequestProperty("connection", "Keep-Alive");
      httpURLConnection.setRequestProperty("Charsert", "UTF-8");
      // 1 min
      httpURLConnection.setConnectTimeout(60000);
      // 1 min
      httpURLConnection.setReadTimeout(60000);

      httpURLConnection.addRequestProperty("userName", userName);
      httpURLConnection.addRequestProperty("passwd", passwd);
      httpURLConnection.addRequestProperty("fileName", remoteFileName);

      // connect to server (tcp)
      httpURLConnection.connect();

      in = httpURLConnection.getInputStream();// send request to
                                // server
      File file = new File(localFileName);
      if(!file.exists()){
        file.createNewFile();
      }

      out = new FileOutputStream(file); 
      byte[] buffer = new byte[4096];
      int readLength = 0;
      while ((readLength=in.read(buffer)) > 0) {
        byte[] bytes = new byte[readLength];
        System.arraycopy(buffer, 0, bytes, 0, readLength);
        out.write(bytes);
      }
      
      out.flush();
    }catch(Exception e){
      e.printStackTrace();
    }finally{
      try {
        if(in != null){
          in.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      
      try {
        if(out != null){
          out.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

3.2 服务端处理

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

public void processDownload(HttpServletRequest request, HttpServletResponse response){
    int BUFFER_SIZE = 4096;
    InputStream in = null;
    OutputStream out = null;
    
    System.out.println("Come on, baby .......");
    
    try{
      request.setCharacterEncoding("utf-8"); 
      response.setCharacterEncoding("utf-8"); 
      response.setContentType("application/octet-stream");
      
      String userName = request.getHeader("userName");
      String passwd = request.getHeader("passwd");
      String fileName = request.getHeader("fileName");
      
      System.out.println("userName:" + userName);
      System.out.println("passwd:" + passwd);
      System.out.println("fileName:" + fileName);
      
      //可以根据传递来的userName和passwd做进一步处理,比如验证请求是否合法等       
      File file = new File(downloadPath + "\\" + fileName);
      response.setContentLength((int) file.length());
      response.setHeader("Accept-Ranges", "bytes");
      
      int readLength = 0;
      
      in = new BufferedInputStream(new FileInputStream(file), BUFFER_SIZE);
      out = new BufferedOutputStream(response.getOutputStream());
      
      byte[] buffer = new byte[BUFFER_SIZE];
      while ((readLength=in.read(buffer)) > 0) {
        byte[] bytes = new byte[readLength];
        System.arraycopy(buffer, 0, bytes, 0, readLength);
        out.write(bytes);
      }
      
      out.flush();
      
      response.addHeader("token", "hello 1");
       
    }catch(Exception e){
      e.printStackTrace();
       response.addHeader("token", "hello 2");
    }finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
        }
      }
      if (out != null) {
        try {
          out.close();
        } catch (IOException e) {
        }
      }
    }
  }

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

以上就是小编为大家带来的使用HttpClient实现文件的上传下载方法全部内容了,希望大家多多支持~


推荐阅读
  • 本文详细介绍如何利用已搭建的LAMP(Linux、Apache、MySQL、PHP)环境,快速创建一个基于WordPress的内容管理系统(CMS)。WordPress是一款流行的开源博客平台,适用于个人或小型团队使用。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 本文详细介绍了如何使用Python编写爬虫程序,从豆瓣电影Top250页面抓取电影信息。文章涵盖了从基础的网页请求到处理反爬虫机制,再到多页数据抓取的全过程,并提供了完整的代码示例。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 本文介绍如何在Java项目中使用Log4j库进行日志记录。我们将详细说明Log4j库的引入、配置及简单应用,帮助开发者快速上手。 ... [详细]
  • 探讨了小型企业在构建安全网络和软件时所面临的挑战和机遇。本文介绍了如何通过合理的方法和工具,确保小型企业能够有效提升其软件的安全性,从而保护客户数据并增强市场竞争力。 ... [详细]
  • 本文详细介绍了如何准备和安装 Eclipse 开发环境及其相关插件,包括 JDK、Tomcat、Struts 等组件的安装步骤及配置方法。 ... [详细]
  • 在本周的白板演练中,Apache Flink 的 PMC 成员及数据工匠首席技术官 Stephan Ewen 深入探讨了如何利用保存点功能进行流处理中的数据重新处理、错误修复、系统升级和 A/B 测试。本文将详细解释保存点的工作原理及其应用场景。 ... [详细]
  • 本文详细介绍了 Flink 和 YARN 的交互机制。YARN 是 Hadoop 生态系统中的资源管理组件,类似于 Spark on YARN 的配置方式。我们将基于官方文档,深入探讨如何在 YARN 上部署和运行 Flink 任务。 ... [详细]
  • 本文探讨了在使用Selenium进行自动化测试时,由于webdriver对象实例化位置不同而导致浏览器闪退的问题,并提供了详细的代码示例和解决方案。 ... [详细]
  • QBlog开源博客系统:Page_Load生命周期与参数传递优化(第四部分)
    本教程将深入探讨QBlog开源博客系统的Page_Load生命周期,并介绍一种简洁的参数传递重构方法。通过视频演示和详细讲解,帮助开发者更好地理解和应用这些技术。 ... [详细]
author-avatar
suny
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有