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

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

使⽤HttpClient实现⽂件的上传下载⽅法
1 HTTP
HTTP 协议可能是现在 Internet 上使⽤得最多、最重要的协议了,越来越多的 Java 应⽤程序需要直接通过 HTTP 协议来访问⽹络资源。

虽然在 JDK 的 包中已经提供了访问 HTTP 协议的基本功能,但是对于⼤部分应⽤程序来说,JDK 库本⾝提供的功能还不够丰富和灵活。

HttpClient ⽤来提供⾼效的、最新的、功能丰富的⽀持 HTTP 协议的客户端编程⼯具包,并且它⽀持HTTP 协议最新的版本和建议。

⼀般的情况下我们都是使⽤Chrome或者其他浏览器来访问⼀个WEB服务器,⽤来浏览页⾯查看信息或者提交⼀些数据、⽂件上传下载等等。

所访问的这些页⾯有的仅仅是⼀些普通的页⾯,有的需要⽤户登录后⽅可使⽤,或者需要认证以及是⼀些通过加密⽅式传输,例如HTTPS。

⽬前我们使⽤的浏览器处理这些情况都不会构成问题。

但是⼀旦我们有需求不通过浏览器来访问服务器的资源呢?那该怎么办呢?
下⾯以本地客户端发起⽂件的上传、下载为例做个⼩Demo。

HttpClient有两种形式,⼀种是org.apache.http下的,⼀种是mons.httpclient.HttpClient。

2 ⽂件上传
⽂件上传可以使⽤两种⽅式实现,⼀种是PostMethod⽅式,⼀种是HttpPost⽅式。

两者的处理⼤同⼩异。

PostMethod是使⽤FileBody将⽂件包装流包装起来,HttpPost是使⽤FilePart将⽂件流包装起来。

在传递⽂件流给服务端的时候,都可以同时传递其他的参数。

2.1 客户端处理
2.1.1 PostMethod⽅式
将⽂件封装到FilePart中,放⼊Part数组,同时,其他参数可以放⼊StringPart中,这⾥没有写,只是单纯的将参数以setParameter的⽅式进⾏设置。

此处的HttpClient是mons.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(stIndexOf("/") + 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是mons.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。

⽬前来说,使⽤mons.httpclient.HttpClient多⼀些。

看⾃⼰了~
以上就是⼩编为⼤家带来的使⽤HttpClient实现⽂件的上传下载⽅法全部内容了,希望⼤家多多⽀持~。

相关文档
最新文档