使用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",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,bytes,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,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,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实现文件的上传下载方法全部内容了,希望大家多多支持编程小技巧~ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |