httpclient结合httpmime实现文件上传

一般我们做文件上传,都是在页面上传到服务器。有时候,我们在做系统的时候,我们需要将文件先上传到我们自己的服务器,然后通过server-to-server的方式上传文件到另一个服务器,如云存储服务器。java中利用httpclient可以实现get,post等http请求,但是如果需要上传文件,需要结合httpmime,将文件作为二进制流加入到post请求体中,这里介绍如何通过httpclient将文件上传到服务器上。

这里开启一个struts2的工程,里面有保存文件上传的方法,将该服务作为httpclient最终需要上传的服务器。关键代码:

package com.xxx.action;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;
public class MainAction {
	
	private File image;
	private String imageFileName;
	private String imageContentType;
	public File getImage() {
		return image;
	}
	public void setImage(File image) {
		this.image = image;
	}
	public String getImageFileName() {
		return imageFileName;
	}
	public void setImageFileName(String imageFileName) {
		this.imageFileName = imageFileName;
	}
	public String getImageContentType() {
		return imageContentType;
	}
	public void setImageContentType(String imageContentType) {
		this.imageContentType = imageContentType;
	}
	
	
	public String uploadByJson() {
		HttpServletRequest request = ServletActionContext.getRequest();
		String checksum = request.getHeader("X-File-Checksum");
		System.out.println(checksum);
		String path = ServletActionContext.getServletContext().getRealPath("/uploads");
		File target = new File(path,imageFileName);
		try {
			FileUtils.copyFile(image, target);
			System.out.println("file -> path "+path);
			HttpServletResponse response = ServletActionContext.getResponse();
			response.setContentType("application/json;charset=UTF-8");
			PrintWriter out = response.getWriter();
			out.println("{\"code\":200,\"status\":\"success\"}");
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

我们来准备httpclient上传的工程,如果是maven工程,我们需要引入httpclient,httpmime两个主要的依赖库。我这里使用的是普通的项目,加入了commons-codec-1.4.jar,httpclient-4.4.1.jar,httpcore-4.4.1.jar,httpmime-4.4.1.jar。

核心的代码:HttpUtils.java

package com.xxx.http;
import java.io.File;
import java.io.IOException;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
public class HttpUtils {
	private static final String 
    URL_PREFIX_STRING="http://127.0.0.1:8080/struts2hack/main!uploadByJson.action";
	//http
	private static final PoolingHttpClientConnectionManager cm;
	private static final CloseableHttpClient HTTP_CLIENT;
	
	static{
		cm = new PoolingHttpClientConnectionManager();
		cm.setMaxTotal(200);
		cm.setDefaultMaxPerRoute(100);
		RequestConfig config = RequestConfig.custom()
					.setConnectTimeout(1000)
					.setSocketTimeout(2000)
					.build();
		HTTP_CLIENT = HttpClientBuilder.create()
					.setConnectionManager(cm)
					.setDefaultRequestConfig(config)
					.build();
	}
	
	public static String upload(File file){
		HttpPost post = new HttpPost(URL_PREFIX_STRING);
		post.addHeader("X-File-Checksum", DigestUtils.md5Hex("123456"));
		MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
		entityBuilder.addPart("image", new FileBody(file));
		entityBuilder.addPart("imageFileName", new StringBody(file.getName(),
        ContentType.MULTIPART_FORM_DATA));
		post.setEntity(entityBuilder.build());
		String result = "";
		try {
			CloseableHttpResponse response = HTTP_CLIENT.execute(post);
			HttpEntity entity = response.getEntity();
			if(entity!=null){
				result =  EntityUtils.toString(entity, "UTF-8");
			}
			EntityUtils.consume(entity);
			response.close();
			System.out.println(result);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	public static void main(String[] args) {
		String path = "C:\\Users\\Administrator\\downloads\\big_img.png";
		File file = new File(path);
		upload(file);
	}
}

上传文件和普通的http请求不同的是,我们的文件要当做一种流的方式传输,而不是当作普通的参数传输,所以我们需要借助MulipartEntityBuilder提供的api,该api是在httpmime包中,所以仅仅是单独的httpclient无法完成这个工作,将文件文件加入到httppost的entity当中。 如果还带有别的参数,可以通过entityBuilder.addPart(paramName,paramValue)的方式增加,如本例中,struts2上传,需要传入imageFileName参数,我们就是通过entityBuilder.addPart("imageFileName", new StringBody(file.getName(),ContentType.MULTIPART_FORM_DATA))来添加的。

你可能感兴趣的:(java)