form, Charset charset) {
this.form = form;
@@ -81,6 +84,13 @@ public class MultipartBody implements RequestBody{
formEnd(out);
}
+ @Override
+ public String toString() {
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ write(out);
+ return IoUtil.toStr(out, this.charset);
+ }
+
// 普通字符串数据
/**
@@ -97,10 +107,26 @@ public class MultipartBody implements RequestBody{
}
/**
- * 添加Multipart表单的数据项
+ * 添加Multipart表单的数据项
+ *
+ * --分隔符(boundary)[换行]
+ * Content-Disposition: form-data; name="参数名"[换行]
+ * [换行]
+ * 参数值[换行]
+ *
+ *
+ * 或者:
+ *
+ *
+ * --分隔符(boundary)[换行]
+ * Content-Disposition: form-data; name="表单名"; filename="文件名"[换行]
+ * Content-Type: MIME类型[换行]
+ * [换行]
+ * 文件的二进制内容[换行]
+ *
*
* @param formFieldName 表单名
- * @param value 值,可以是普通值、资源(如文件等)
+ * @param value 值,可以是普通值、资源(如文件等)
* @param out Http流
* @throws IORuntimeException IO异常
*/
@@ -113,25 +139,63 @@ public class MultipartBody implements RequestBody{
return;
}
+ // --分隔符(boundary)[换行]
write(out, "--", BOUNDARY, StrUtil.CRLF);
- if(value instanceof Resource){
- // 文件资源(二进制资源)
- final Resource resource = (Resource)value;
- final String fileName = resource.getName();
- write(out, StrUtil.format(CONTENT_DISPOSITION_FILE_TEMPLATE, formFieldName, ObjectUtil.defaultIfNull(fileName, formFieldName)));
- // 根据name的扩展名指定互联网媒体类型,默认二进制流数据
- write(out, StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE, HttpUtil.getMimeType(fileName, "application/octet-stream")));
- resource.writeTo(out);
- } else{
- // 普通数据
+ if (value instanceof Resource) {
+ appendResource(formFieldName, (Resource) value, out);
+ } else {
+ /*
+ * Content-Disposition: form-data; name="参数名"[换行]
+ * [换行]
+ * 参数值
+ */
write(out, StrUtil.format(CONTENT_DISPOSITION_TEMPLATE, formFieldName));
+ write(out, StrUtil.CRLF);
write(out, value);
}
write(out, StrUtil.CRLF);
}
+ /**
+ * 添加Multipart表单的Resource数据项,支持包括{@link HttpResource}资源格式
+ *
+ * @param formFieldName 表单名
+ * @param resource 资源
+ * @param out Http流
+ * @throws IORuntimeException IO异常
+ */
+ private void appendResource(String formFieldName, Resource resource, OutputStream out) throws IORuntimeException {
+ final String fileName = resource.getName();
+
+ // Content-Disposition
+ if (null == fileName) {
+ // Content-Disposition: form-data; name="参数名"[换行]
+ write(out, StrUtil.format(CONTENT_DISPOSITION_TEMPLATE, formFieldName));
+ } else {
+ // Content-Disposition: form-data; name="参数名"; filename="文件名"[换行]
+ write(out, StrUtil.format(CONTENT_DISPOSITION_FILE_TEMPLATE, formFieldName, fileName));
+ }
+
+ // Content-Type
+ if (resource instanceof HttpResource) {
+ final String contentType = ((HttpResource) resource).getContentType();
+ if (StrUtil.isNotBlank(contentType)) {
+ // Content-Type: 类型[换行]
+ write(out, StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE, contentType));
+ }
+ } else {
+ // 根据name的扩展名指定互联网媒体类型,默认二进制流数据
+ write(out, StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE,
+ HttpUtil.getMimeType(fileName, ContentType.OCTET_STREAM.getValue())));
+ }
+
+ // 内容
+ write(out, "\r\n");
+ resource.writeTo(out);
+ }
+
/**
* 上传表单结束
*
diff --git a/hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java b/hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java
new file mode 100644
index 000000000..edca37138
--- /dev/null
+++ b/hutool-http/src/test/java/cn/hutool/http/body/MultipartBodyTest.java
@@ -0,0 +1,27 @@
+package cn.hutool.http.body;
+
+import cn.hutool.core.io.resource.StringResource;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.http.HttpResource;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MultipartBodyTest {
+
+ @Test
+ public void buildTest(){
+ Map form = new HashMap<>();
+ form.put("pic1", "pic1 content");
+ form.put("pic2", new HttpResource(
+ new StringResource("pic2 content"), "text/plain"));
+ form.put("pic3", new HttpResource(
+ new StringResource("pic3 content", "pic3.jpg"), "image/jpeg"));
+
+ final MultipartBody body = MultipartBody.create(form, CharsetUtil.CHARSET_UTF_8);
+
+ Assert.assertNotNull(body.toString());
+ }
+}