在开发中,我们使用的比较多的HTTP请求方式基本上就是GET、POST。其中GET用于从服务器获取数据,POST主要用于向服务器提交一些表单数据,例如文件上传等。而我们在使用HTTP请求时中遇到的比较麻烦的事情就是构造文件上传的HTTP报文格式,这个格式虽说也比较简单,但也比较容易出错。今天我们就一起来学习HTTP POST的报文格式以及通过Java来模拟文件上传的请求。
啥都不说直接上代码,能用记得点赞:
/**
*
* @Function: HttpClient.java 上传文件到指定地址URL
* @param urlStr 请求地址
* @param files 文件map集合
* @param params 参数集合
*
* @version: v1.0.0
* @author: 白毅
* @date: 2019年2月22日 下午5:33:41
*/
public String uploadFile(String urlStr, Map<String, File> files, Map<String, String> params) {
try {
// 换行符
final String LINEND = "\r\n", MULTIPART_FROM_DATA = "multipart/form-data", PREFIX = "--";
String BOUNDARY = java.util.UUID.randomUUID().toString();
boolean isFirst = true;
// 服务器的上传地址
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置为POST情
conn.setRequestMethod("POST");
// 发送POST请求必须设置如下两行
conn.setDoInput(true);// 允许输入
conn.setDoOutput(true);// 允许输出
conn.setUseCaches(false); // 不允许使用缓存
// 设置请求头参数
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Charsert", "UTF-8");
conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + "; boundary=" + PREFIX + PREFIX + BOUNDARY);
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36");
// 首先组拼文本类型的参数
StringBuffer sb = new StringBuffer();
sb.append(LINEND);
for (Map.Entry<String, String> entry : params.entrySet()) {
// 参数头
sb.append(PREFIX);
sb.append(PREFIX);
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINEND);
sb.append("Content-Disposition: form-data; name=\"");
sb.append(entry.getKey());
sb.append("\"");
// 参数头设置完以后需要两个换行,然后才是参数内容
sb.append(LINEND);
sb.append(LINEND);
sb.append(entry.getValue());
sb.append(LINEND);
}
// 文件数据传输
OutputStream out = new DataOutputStream(conn.getOutputStream());
for (Map.Entry<String, File> file : files.entrySet()) {
if (!isFirst) {
sb = new StringBuffer();
}
// 参数头
sb.append(PREFIX);
sb.append(PREFIX);
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINEND);
sb.append("Content-Disposition: form-data; name=\"");
sb.append(file.getKey());
sb.append("\";");
sb.append(" filename=\"");
sb.append(file.getKey());
sb.append("\"");
sb.append(LINEND);
sb.append("Content-Type: ");
sb.append(new MimetypesFileTypeMap().getContentType(file.getValue().getName()));
// 参数头设置完以后需要两个换行,然后才是参数内容
sb.append(LINEND);
sb.append(LINEND);
// 将参数的数据写入到输出流中
out.write(sb.toString().getBytes());
// 数据输入流,用于读取文件数据
InputStream is = new FileInputStream(file.getValue());
DataInputStream in = new DataInputStream(is);
byte[] bufferOut = new byte[2048];
int bytes = 0;
// 每次读2KB数据,并且将文件数据写入到输出流中
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
// 最后添加换行
out.write(LINEND.getBytes());
in.close();
isFirst = false;
}
// 定义最后数据分隔线
sb.append(PREFIX).append(PREFIX).append(PREFIX).append(BOUNDARY).append(PREFIX);
// 写上结尾标识
out.write(sb.toString().getBytes());
out.flush();
out.close();
// 得到响应码
int res = conn.getResponseCode();
StringBuffer buffer = new StringBuffer();
if (res == 200) {
// 读取返回数据
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
reader.close();
}
conn.disconnect();
return buffer.toString();
} catch (Exception e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
}
return "";
}
来源:CSDN
作者:白凯锐大师
链接:https://blog.csdn.net/qq_40770916/article/details/87883049