使用原生JDK写一个HttpClient发送POST上传图片和表单数据

使用原生JDK写一个HttpClient发送POST上传图片和表单数据

使用HttpUrlConnection
一个支持HTTP特定功能的URLConnection。

使用这个类遵循以下模式:

1.通过调用URL.openConnection()来获得一个新的HttpURLConnection对象,并且将其结果强制转换为HttpURLConnection.

2.准备请求。一个请求主要的参数是它的URI。请求头可能也包含元数据,例如证书,首选数据类型和会话cookies.

3.可以选择性的上传一个请求体。HttpURLConnection实例必须设置setDoOutput(true),如果它包含一个请求体。通过将数据写入一个由getOutStream()返回的输出流来传输数据。

4.读取响应。响应头通常包含元数据例如响应体的内容类型和长度,修改日期和会话cookies。响应体可以被由getInputStream返回的输入流读取。如果响应没有响应体,则该方法会返回一个空的流。

5.关闭连接。一旦一个响应体已经被阅读后,HttpURLConnection 对象应该通过调用disconnect()关闭。断开连接会释放被一个connection占有的资源,这样它们就能被关闭或再次使用。

主要的流程

创建URL实例,打开URLConnection

URL url=new URL("http://www.baidu.com");
HttpURLConnection connection= (HttpURLConnection) url.openConnection();

设置连接参数
常用方法:

setDoInput

setDoOutput

setIfModifiedSince:设置缓存页面的最后修改时间(参考自:http://blog.csdn.net/stanleyqiu/article/details/7717235)

setUseCaches

setDefaultUseCaches

setAllowUserInteraction

setDefaultAllowUserInteraction

setRequestMethod:HttpURLConnection默认给使用Get方法

设置请求头参数
常用方法:

setRequestProperty(key,value)

addRequestProperty(key,value)

setRequestProperty和addRequestProperty的区别就是,setRequestProperty会覆盖已经存在的key的所有values,有清零重新赋值的作用。而addRequestProperty则是在原来key的基础上继续添加其他value。

常用设置:

设置请求数据类型:

connection.setRequestProperty("Content-type","application/x-javascript->json");//json格式数据

connection.addRequestProperty("Content-Type","application/x-www-form-urlencoded");//默认浏览器编码类型,http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html

connection.addRequestProperty("Content-Type","multipart/form-data;boundary="+boundary);//post请求,上传数据时的编码类型,并且指定了分隔符

Connection.setRequestProperty("Content-type", "application/x-java-serialized-object");// 设定传送的内容类型是可序列化的java对象(如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
connection.addRequestProperty("Connection","Keep-Alive");//设置与服务器保持连接
connection.addRequestProperty("Charset","UTF-8");//设置字符编码类型

连接并发送请求
connect

getOutputStream

在这里getOutStream会隐含的进行connect,所以也可以不调用connect

获取响应数据
getContent (https://my.oschina.net/zhanghc/blog/134591)

getHeaderField:获取所有响应头字段

getInputStream

getErrorStream:若HTTP响应表明发送了错误,getInputStream将抛出IOException。调用getErrorStream读取错误响应。

post上传文件和表单数据:


import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Map;


/**
 * post文件上传 JDK
 */
public class UploadFile {


  /**
	 * 上传文件到指定Url
	 * @param url  请求地址
	 * @param file	上传文件
	 * @param params 其他参数集合
	 * @param header 请求头
	 * @return
	 */
	public static String uploadFile(String url, File file, Map<String, String> params, Map<String,String> header) {

		String message = "";
		String boundary = "******";		//随机分割线

		InputStream inputStream = null;
		FileInputStream fileInputStream = null;
		OutputStream outputStream = null;
		HttpURLConnection connection = null;
		try {
			URL url1 = new URL(url);
			connection = (HttpURLConnection) url1.openConnection();
			connection.setRequestMethod("POST");
			connection.addRequestProperty("Connection", "Keep-Alive");
			connection.addRequestProperty("Charset", "UTF-8");
			connection.addRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

			//添加请求头
			for (Map.Entry<String, String> entry:header.entrySet()){
				connection.addRequestProperty(entry.getKey(),entry.getValue());
			}

			// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在
			// http正文内,因此需要设为true, 默认情况下是false;
			connection.setDoOutput(true);
			//设置是否从httpUrlConnection读入,默认情况下是true;
			connection.setDoInput(true);
			// Post 请求不能使用缓存  ?
			connection.setUseCaches(false);
			connection.setConnectTimeout(20000);
			outputStream = connection.getOutputStream();

			StringBuilder sb = new StringBuilder();
			if (file != null) {
				//文件上传
				fileInputStream = new FileInputStream(file);
				sb.append("--" + boundary + "\r\n")
						.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + URLEncoder.encode(file.getName(), "UTF-8") + "\"\r\n")
						.append("Content-Type: application/pdf"+"\r\n")
						.append("\r\n");
				/*outputStream.write(("--" + boundary + "\r\n").getBytes("utf-8"));

				// 设定传送的内容类型是可序列化的java对象
				// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
				outputStream.write(("Content-Disposition: form-data; name=\"file\"; filename=\"" + URLEncoder.encode(file.getName(), "UTF-8") + "\"\r\n").getBytes("utf-8"));
				outputStream.write(("Content-Type: application/pdf"+"\r\n").getBytes("utf-8"));*/
				outputStream.write(sb.toString().getBytes("utf-8"));
				byte[] b = new byte[1024];
				while ((fileInputStream.read(b)) != -1) {
					outputStream.write(b);
				}
				outputStream.write(("\r\n").getBytes("utf-8"));
			}

			//数据上传
			for (Map.Entry<String, String> entry:params.entrySet()){
				sb.append("\r\n")
						.append("--" + boundary + "\r\n")
						.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n")
						.append("\r\n")
						.append(entry.getValue() + "\r\n");
			}
			sb.append("--" + boundary +"--"+ "\r\n");
			outputStream.write(sb.toString().getBytes("utf-8"));

			if (connection.getResponseCode() >= 300) {
				throw new Exception("HTTP Request is not success, Response code is " + connection.getResponseCode());
			}


			if (connection.getResponseCode() == 200) {

				inputStream = connection.getInputStream();
				Reader reader = new InputStreamReader(inputStream, "utf-8");
				StringBuilder response = new StringBuilder();

				final char[] buff = new char[1024];
				int read = 0;
				while ((read = reader.read(buff)) > 0) {
					response.append(buff, 0, read);
				}

				return response.toString();
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fileInputStream != null) {
				try {
					fileInputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			connection.disconnect();

		}
		return message;
	}

这里需要指出:

通过chrome的开发工具截取的头信息可以看到:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过post上传数据时,若除了文本数据以外还要需要上传文件,则需要在指定每一条数据的Content-Disposition,name,若是文件还要指明filename,并在每条数据传输的后面用“–”加上boundary隔开,并且需要在第四行用“\r\n”换行符隔开,在最后一行也要用“–”加上boundary加上“–”隔开,否则会导致文件上传失败!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值