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实现文件的上传下载的更多相关文章

  1. 在Window的IIS中创建FTP的Site并用C#进行文件的上传下载

    文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服务器计算机上. 然后,远程计算机可以使用 FTP ...

  2. 创建FTP的Site并用C#进行文件的上传下载

    创建FTP的Site并用C#进行文件的上传下载 文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服 ...

  3. linux链接及文件互相上传下载

    若排版紊乱可查看我的个人博客原文地址 基本操作 本篇博客主要介绍如何去链接远程的linux主机及如何实现本地与远程主机之间文件的上传下载操作,下面的linux系统是CentOS6.6 链接远程linu ...

  4. Spring实现文件的上传下载

    背景:之前一直做的是数据库的增删改查工作,对于文件的上传下载比较排斥,今天研究了下具体的实现,发现其实是很简单.此处不仅要实现单文件的上传,还要实现多文件的上传. 单文件的下载知道了,多文件的下载呢? ...

  5. SocketIo+SpringMvc实现文件的上传下载

    SocketIo+SpringMvc实现文件的上传下载 socketIo不仅可以用来做聊天工具,也可以实现局域网(当然你如果有外网也可用外网)内实现文件的上传和下载,下面是代码的效果演示: GIT地址 ...

  6. JAVAWEB之文件的上传下载

    文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将 ...

  7. SSM框架之中如何进行文件的上传下载

    SSM框架的整合请看我之前的博客:http://www.cnblogs.com/1314wamm/p/6834266.html 现在我们先看如何编写文件的上传下载:你先看你的pom.xml中是否有文件 ...

  8. python使用ftplib模块实现FTP文件的上传下载

    python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def uplo ...

  9. php文件夹上传下载控件分享

    用过浏览器的开发人员都对大文件上传与下载比较困扰,之前遇到了一个php文件夹上传下载的问题,无奈之下自己开发了一套文件上传控件,在这里分享一下.希望能对你有所帮助. 以下是实例的部分脚本文件 这里我先 ...

随机推荐

  1. jsp中@import导入外部样式表与link链入外部样式表的区别

    昨天碰到同事问了一个问题,@impor导入外部样式与link链入外部样式的优先级是怎样的,为什么实验的结果是按照样式表导入后的位置来决定优先级.今天就这个问题具体总结如下:   先解释一下网页添加cs ...

  2. java-基础练习题1

    /** 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,* 假如兔子都不死,问每个月的兔子总数为多少?* 1.程序分析: 兔子的规律为数列1, ...

  3. [HDOJ2830]Matrix Swapping II(胡搞)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2830 给一个矩阵只有0和1,矩阵的列可以和其他列交换无数次,问交换后整个矩阵形成的最大的全是1的子矩阵 ...

  4. Java深入学习之--初始化

    目录 1.方法重载 2.默认构造器 3.this关键字 4.static关键字 5.初始化 1.方法重载 java中方法重载的意思是在同一个类中可以存在方法名相同的方法,而方法的参数类型不同,即使两个 ...

  5. JAVA设计模式之【工厂方法模式】

    看例子 1.TV产品接口,负责播放 public interface TV // TV接口 { public void play(); } 2.TV工厂接口,负责生产产品 public interfa ...

  6. Quickhit快速击键

    一.项目分析 根据输入速率和正确率将玩家分为不同等级,级别越高,一次显示的字符数越多,玩家正确输入一次的得分也越高.如果玩家在规定时间内完成规定次数的输入,正确率达到规定要求,则玩家升级.玩家最高级别 ...

  7. Spring3.1新特性介绍

    Spring3.1新特性 一.Spring2.5之前,我们都是通过实现Controller接口或其实现来定义我们的处理器类.   二.Spring2.5引入注解式处理器支持,通过@Controller ...

  8. HDU 3790 最短路径问题【Dijkstra】

    题意:给出n个点,m条边,每条边的长度d和花费p,给出起点和终点的最短距离和花费,求最短距离,如果有多个最短距离,输出花费最少的 在用dijkstra求最短距离的时候,再用一个f[]数组保存下最少花费 ...

  9. linux中备份mysql数据库的一个shell脚本

    #!/bin/bash #FileName:select_into_bak.sh #Desc:Use select into outfile to backup db or tables #Creat ...

  10. 关于"user.dir"的认识

    最近阅读了一些tomcat源码,看到tomcat在读取jar包外配置文件,是将“user.dir”的路径作为home path文件即 通过System.getProperty("user.d ...