总结一下公司项目中使用到的在后端java进行form表提交给文件上传接口
- 首先我们通过chrome的network查看下在前台调用文件上传接口的请求是怎么样的:
第一个红框中表示了该请求类型为multipart/form-data;在前台来说就是设置了html中form的enctype属性;后面的那个boundary就是上传文件参数的分隔符在下面的具体post内容中可以看到,只是个分隔符自己可以定义。
第三个红框中表示了该请求的post参数,这个看后端怎么定义需要哪些参数:
这里需要关注下后面java构造数据时换行符的问题,它遵循的规则就是一个分隔符+"\r\n"一个content-Disposition+"\r\n"(其中这个的含义就是form中的文件关键字:比如filename,filesize等看后端需要什么),然后再第三行需要一个空的"\r\n"也就是在值的前面,还可以理解为一到值前面就需要2个"\r\n"。 - 在看下后端如何拼接成模拟前台的格式
这里java端其实充当的就是发起个http请求而已
try {
String fileName = "E:/xxx.pdf";
String fileName2 = "xxxx.pdf";
//这里使用fildder进行抓包查看请求状态
System.setProperty("http.proxyHost", "localhost");
System.setProperty("http.proxyPort", "8888");
// 换行符
final String newLine = "\r\n";
final String boundaryPrefix = "--";
// 定义数据分隔线
String BOUNDARY = "========7d4a6d158c9";
// 服务器的域名
//URL url = new URL("http://ip:8080/xxx/fileupaload?SaveFolder=javaTest&encrypt=false");
URL url = new URL("http://ip:8080/xx/fileupaload?SaveFolder=scanfiles\\\\2018");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 设置为POST情
conn.setRequestMethod("POST");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求头参数
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Charsert", "UTF-8");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
OutputStream out = new DataOutputStream(conn.getOutputStream());
// 上传文件
File file = new File(fileName);
StringBuilder sb = new StringBuilder();
sb.append(boundaryPrefix);
sb.append(BOUNDARY);
sb.append(newLine);
//id
sb.append("Content-Disposition: form-data; name=\"id\"");
sb.append(newLine);
sb.append("Content-Type:text/plain; charset=UTF-8");
sb.append(newLine);
sb.append("Content-Transfer-Encoding: 8bit");
sb.append(newLine);
sb.append(newLine);
sb.append("123");
//name
sb.append(newLine);
sb.append(BOUNDARY);
sb.append(newLine);
sb.append("Content-Disposition: form-data; name=\"name\"");
sb.append(newLine);
sb.append("Content-Type:text/plain; charset=UTF-8");
sb.append(newLine);
sb.append("Content-Transfer-Encoding: 8bit");
sb.append(newLine);
sb.append(newLine);
sb.append("lijiaxin_test.pdf");
//file
sb.append(newLine);
sb.append(BOUNDARY);
sb.append(newLine);
sb.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName
+ "\"" + newLine);
sb.append("Content-Type:application/octet-stream");
// 参数头设置完以后需要两个换行,然后才是参数内容
sb.append(newLine);
sb.append("Content-Transfer-Encoding: binary");
sb.append(newLine);
sb.append(newLine);
// 将参数头的数据写入到输出流中
out.write(sb.toString().getBytes());
System.out.println(sb.toString());
// 数据输入流,用于读取文件数据
DataInputStream in = new DataInputStream(new FileInputStream(
file));
byte[] bufferOut = new byte[1024];
int bytes = 0;
// 每次读1KB数据,并且将文件数据写入到输出流中
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
// 最后添加换行
out.write(newLine.getBytes());
in.close();
// 定义最后数据分隔线,即--加上BOUNDARY再加上--。
byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine)
.getBytes();
// 写上结尾标识
out.write(end_data);
out.flush();
out.close();
// 定义BufferedReader输入流来读取URL的响应
// BufferedReader reader = new BufferedReader(new InputStreamReader(
// conn.getInputStream()));
// String line = null;
// while ((line = reader.readLine()) != null) {
// System.out.println(line);
// }
StringBuffer strBuf = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
strBuf.append(line).append("\n");
}
String res = strBuf.toString();
reader.close();
reader = null;
System.out.println(res.toString());
} catch (Exception e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
}
这里容易出问题的几个点:
1.在最开头设置边界时,需要多两个“–”
2.边界值自己设定 boundry
3.然后值前面有两个换行
4.最后一行还需要一层边界值来包围,需要多两个"–"收尾
5.content-type需要设置成:multipart/form-data; boundary=—xxxxxxxxx