环球视讯!使用HttpClient实现文件的上传下载方法

时间:2022-10-01 19:42:31       来源:互联网

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()          // 相当于<input type="file" name="file"/>          .addPart("file", bin)                    // 相当于<input type="text" name="userName" value=userName>          .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<FileItem> items = null;              try {         // 解析request请求         items = upload.parseRequest(request);       } catch (FileUploadException e) {         e.printStackTrace();       }             if(items!=null){         //解析表单项目         Iterator<FileItem> iter = items.iterator();         while (iter.hasNext()) {           FileItem item = iter.next();                     //如果是普通表单属性           if (item.isFormField()) {             //相当于input的name属性  <input type="text" name="content">             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实现文件的上传下载方法全部内容了,希望大家多多支持~

关键词: httpclient 上传文件