springboot multipart/form-data;文件上传请求组装
工作需要后台上传文件。自行组装文件上传类
form-data 文件的基本形式
- 1、请求体需分隔符:
-----------------------------152909417026772332233306781192
来组装。一个分隔符下一个请求参数。分隔符是随机的。 - 2、最后一个参附上文件描述和文件的字节流
- 3、以分隔符加
--
标记结尾:-----------------------------152909417026772332233306781192--
/**
* ======================== 请求体范例 ===========================
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="type"
*
* image
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="app_id"
*
* 1643192118890183
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="is_waterlog"
*
* 1
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="save_material"
*
* 1
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="no_compress"
*
* 0
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="is_events"
*
*
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="article_type"
*
* news
* -----------------------------152909417026772332233306781192
* Content-Disposition: form-data; name="media"; filename="timg.jpeg"
* Content-Type: image/jpeg
*
* {这里是文件流}
* -----------------------------152909417026772332233306781192--
*/
代码
import org.apache.http.util.ByteArrayBuffer;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.FileNameMap;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
/**
*
* 请求中 form-data 的抽象
*/
public class FileFormData {
private static final String ENCODE = "utf-8";
//分隔符号
private static String delimiter = "7dc641c2e0260";
//自定body
private static HashMap<String, String> paramMap;
//文件body参数
private static String fileFiledName;
private static String fileName;
private static String fileType;
private static String fileUrl;
/**
*
* @param fileFiledName 表单文件部分的filedname: Content-Disposition: form-data; name="{fileFiledName}"; filename="timg.jpeg"
* @param fileName 表单文件部分的filename: Content-Disposition: form-data; name="{fileFiledName}"; filename="{fileName}"
* @param fileType 表单文件部分的content-type: Content-Type: {fileType}
* @param fileUrl 文件资源定位符
*/
public FileFormData(String fileFiledName, String fileName, String fileType, String fileUrl){
paramMap = new HashMap<>();
FileFormData.fileFiledName = fileFiledName;
FileFormData.fileName = fileName;
FileFormData.fileType = fileType;
FileFormData.fileUrl = fileUrl;
}
public static String getDelimiter() {
return delimiter;
}
/**
* 分隔符设定。需指定分隔符时使用
* @param delimiter
*/
public static void setDelimiter(String delimiter) {
FileFormData.delimiter = delimiter;
}
/**
* 获取header contextType 一般是默认的。只需覆盖header就行。
* 但如果特殊平台检测上传分隔符, 则需先设置 特有的分隔符
* 其他关键参数默认随之生成
* context-type: multipart/form-data;boundary=---------------------------{delimiter}
* 分隔符: -----------------------------{delimiter}\r\n
* 终止符: -----------------------------{delimiter}--\r\n
* @param delimiter
*/
public String getHeaderContextType(String delimiter) {
FileFormData.delimiter = delimiter;
return "multipart/form-data; boundary=---------------------------" + FileFormData.delimiter;
}
String getHeaderContextType() {
return "multipart/form-data; boundary=---------------------------" + FileFormData.delimiter;
}
public void put(String key, String val){
paramMap.put(key, val);
}
byte[] getFormDataBody() throws IOException {
String delimiter = "-----------------------------"+ FileFormData.delimiter +"\r\n";
String over = "-----------------------------"+ FileFormData.delimiter +"--\r\n";
//自定参数组装
ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(10);
for (Map.Entry<String, String> param : paramMap.entrySet()) {
if (!((param.getKey() == null) || (param.getKey().length() == 0))) {
byte[] headByte = delimiter.getBytes(ENCODE);
byteArrayBuffer.append(headByte, 0, headByte.length);
String textTemplate = "Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n";
String text = String.format(textTemplate, param.getKey(), param.getValue());
byte[] textByte = text.getBytes(ENCODE);
byteArrayBuffer.append(textByte, 0, textByte.length);
}
}
//当传入的fileType为空时 获取content-type
if(FileFormData.fileType.equals("")){
FileNameMap fileNameMap = URLConnection.getFileNameMap();
FileFormData.fileType = fileNameMap.getContentTypeFor(fileUrl);
System.out.println("file type:"+FileFormData.fileType);
}
//文件参数组装
String end = "\r\n";
String textTemplate = "Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n";
textTemplate += "Content-Type: %s\r\n\r\n";
String fileFormHeadStr = String.format(textTemplate, fileFiledName, fileName, fileType);
byte[] headBytes = fileFormHeadStr.getBytes(ENCODE);
byte[] fileDatas = null;
byte[] endBytes = end.getBytes(ENCODE);
// over 是最重的终止符号,终止后整个请求body组装完毕
byte[] overBytes = over.getBytes(ENCODE);
//加载文件的字节流
URL url = new URL(FileFormData.fileUrl);
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
if (is == null) return new byte[0];
fileDatas = StreamUtil.convertToBytes(is);
ByteArrayOutputStream totals = new ByteArrayOutputStream();
totals.write(byteArrayBuffer.toByteArray());
totals.write(delimiter.getBytes(ENCODE));
totals.write(headBytes);
if (fileDatas != null) {
totals.write(fileDatas);
} else {
totals.close();
return new byte[0];
}
totals.write(endBytes);
totals.write(overBytes);
byte[] resTotals = totals.toByteArray();
totals.close();
System.out.println(totals.toString());
return resTotals;
}
}
使用范例
FileFormData postForm = new FileFormData("media","abc.jpg", "image/jpeg", "图片的完整可访问路径");
postForm.put("type","image");
postForm.put("666","666");
postForm.put("777","777");
String url = "上传地址";
byte[] body = postForm.getFormDataBody();
//header 自定
//将body作为请求体发起请求即可。
以上