我有一个HTML表单,里面有一个文件上传。我正试图使用MultipartEntityBuilder
通过表单上传Word文档,但它不起作用。
表单有几个文本输入和2个文件上传行。如果我使用BasicNameValuePair
方法并将这些字段设置为空Strings,则文本字段将正确提交。因为我需要上传文件,所以我改成了MultipartEntityBuilder
,甚至不能让基本的测试再次工作。
工作守则
HttpClient client = HttpClientBuilder.create().build();
String uploadUrl = "http://somepage.com/upload";
HttpPost httppost = new HttpPost(uploadUrl);
httppost.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
httppost.setHeader("Content-Type", "multipart/form-data");
httppost.setHeader("Accept-Encoding", "gzip, deflate");
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("testField1", "Value1"));
formparams.add(new BasicNameValuePair("testField2", "Value2"));
formparams.add(new BasicNameValuePair("fileField1", ""));
formparams.add(new BasicNameValuePair("fileField2", ""));
httppost.setEntity(new UrlEncodedFormEntity(formparams, Consts.UTF_8));
HttpResponse response = client.execute(httppost, httpContext);
正在尝试MultipartEntityBuilder
// Everything up to and including the Headers remain the same
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
StringBody sb = new StringBody("Value1", ContentType.TEXT_PLAIN);
builder.addPart("textField1", sb);
sb = new StringBody("Value2", ContentType.TEXT_PLAIN);
builder.addPart("textField2", sb);
FileBody fb = new FileBody(new File("path to file"), ContentType.DEFAULT_BINARY);
builder.addPart("fileField1", fb);
fb = new FileBody(new Field("path to file2"), ContentType.DEFAULT_BINARY);
builder.addPart("fileField2", fb);
httppost.setEntity(builder.build());
HttpResponse response = client.execute(httppost, httpContext);
该表单由Oracle托管并返回错误:
发生意外错误:ORA-06501:PL/SQL:程序错误
我还尝试了以下其他方法:
builder.addTextBody("textField1", "Value1");
builder.addTextBody("textField2", "Value2");
File file1 = new File("path to file1");
builder.addBinaryBody("fileField1", file1, ContentType.DEFAULT_BINARY, file1.getName());
File file2 = new File("path to file2");
builder.addBinaryBody("fileField2", file2, ContentType.DEFAULT_BINARY, file2.getName());
以及尝试通过将所有内容放入builder.addTextBody()
来模拟我的第一个测试,就像我最初的工作测试一样,但仍然得到相同的结果。
伐木
根据@oleg请求,我已发布了此次通话的通话记录:
DEBUG [org.apache.http.client.protocol.RequestAddCookies] CookieSpec selected: default
DEBUG [org.apache.http.client.protocol.RequestAddCookies] Cookie [version: 0][name: SSO_TIMEOUT_ID][value: v1.0~83BA4EF3DA76C07B55F93B5C5D65F90947314693035F046BFCC21BCD37F8B95284E732E711971532B182F90AE461E320FCCC74452BAF4A16FB6E5EFA5F86985B26C95D30001D9ACC3BE8E9D2786B1CD38A79788FC7623FCE06C84266C234638182D44786E4971B53EBFC25FD3B7A565F][domain: isomething.com][path: /][expiry: null] match [wwwdev.isomething.com:80/portal/pls/cust_portal/!CUST_PORTAL.wwa_app_module.accept]
DEBUG [org.apache.http.client.protocol.RequestAddCookies] Cookie [version: 0][name: cust_portal][value: 9.0.3+en-us+us+AMERICA+12955AE0CEA20F3CE050558C15F00BD2+84676D40A18761D45DEBA039A78FF868CA9B49F2DEA2D283DE61561CE0F547D3A27C643219F1E6C867CF150CDEA69AE9844407F570B4BBD967491098CECEEA836861C9FF1F06AF7929814DF3C55426F1C2E73C91B219801B][domain: wwwdev.isomething.com][path: /][expiry: null] match [wwwdev.isomething.com:80/portal/pls/cust_portal/!CUST_PORTAL.wwa_app_module.accept]
DEBUG [org.apache.http.client.protocol.RequestAuthCache] Auth cache not set in the context
DEBUG [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection request: [route: {}->http://wwwdev.isomething.com:80][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
DEBUG [org.apache.http.impl.conn.PoolingHttpClientConnectionManager] Connection leased: [id: 4][route: {}->http://wwwdev.isomething.com:80][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
DEBUG [org.apache.http.impl.execchain.MainClientExec] Opening connection {}->http://wwwdev.isomething.com:80
DEBUG [org.apache.http.impl.conn.DefaultHttpClientConnectionOperator] Connecting to wwwdev.isomething.com/141.146.161.39:80
DEBUG [org.apache.http.impl.conn.DefaultHttpClientConnectionOperator] Connection established 10.0.0.2:49827<->141.146.161.39:80
DEBUG [org.apache.http.impl.execchain.MainClientExec] Executing request POST /portal/pls/cust_portal/!CUST_PORTAL.wwa_app_module.accept HTTP/1.1
DEBUG [org.apache.http.impl.execchain.MainClientExec] Target auth state: UNCHALLENGED
DEBUG [org.apache.http.impl.execchain.MainClientExec] Proxy auth state: UNCHALLENGED
DEBUG [org.apache.http.headers] http-outgoing-4 >> POST /portal/pls/cust_portal/!CUST_PORTAL.wwa_app_module.accept HTTP/1.1
DEBUG [org.apache.http.headers] http-outgoing-4 >> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
DEBUG [org.apache.http.headers] http-outgoing-4 >> Origin: http://wwwdev.isomething.com
DEBUG [org.apache.http.headers] http-outgoing-4 >> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36
DEBUG [org.apache.http.headers] http-outgoing-4 >> Referer: http://wwwdev.isomething.com/portal/page/cust_portal/SOM_PGR/ReportManager2/ReportManager/SOM_Reports_MTC/SOM_FILE_CLERK_ADD_REPORT?np_report_number=MTC01234567&np_project_number=3141307&np_country=US&np_customer_number=110960&np_module=URM&np_customer_name=MY TEST CENTRAL TEST ACCOUNT
DEBUG [org.apache.http.headers] http-outgoing-4 >> Accept-Encoding: gzip, deflate
DEBUG [org.apache.http.headers] http-outgoing-4 >> Accept-Language: en-US,en;q=0.8
DEBUG [org.apache.http.headers] http-outgoing-4 >> DNT: 1
DEBUG [org.apache.http.headers] http-outgoing-4 >> Content-Length: 49234
DEBUG [org.apache.http.headers] http-outgoing-4 >> Content-Type: multipart/form-data; boundary=_I6HZ69Fquh0RHe-DNWGs9tfX48pemmkOYs
DEBUG [org.apache.http.headers] http-outgoing-4 >> Host: wwwdev.isomething.com
DEBUG [org.apache.http.headers] http-outgoing-4 >> Connection: Keep-Alive
DEBUG [org.apache.http.headers] http-outgoing-4 >> Cookie: SSO_TIMEOUT_ID=v1.0~83BA4EF3DA76C07B55F93B5C5D65F90947314693035F046BFCC21BCD37F8B95284E732E711971532B182F90AE461E320FCCC74452BAF4A16FB6E5EFA5F86985B26C95D30001D9ACC3BE8E9D2786B1CD38A79788FC7623FCE06C84266C234638182D44786E4971B53EBFC25FD3B7A565F; cust_portal=9.0.3+en-us+us+AMERICA+12955AE0CEA20F3CE050558C15F00BD2+84676D40A18761D45DEBA039A78FF868CA9B49F2DEA2D283DE61561CE0F547D3A27C643219F1E6C867CF150CDEA69AE9844407F570B4BBD967491098CECEEA836861C9FF1F06AF7929814DF3C55426F1C2E73C91B219801B
DEBUG [org.apache.http.headers] http-outgoing-4 << HTTP/1.1 200 OK
DEBUG [org.apache.http.headers] http-outgoing-4 << Cache-Control: max-age=0
DEBUG [org.apache.http.headers] http-outgoing-4 << Content-Type: text/html; charset=UTF-8
DEBUG [org.apache.http.headers] http-outgoing-4 << Set-Cookie: SSO_TIMEOUT_ID=v1.0~83BA4EF3DA76C07B68FCC2530F599A0EC0C64F824C7AE3F72C95A8D07625F4915248DB9B7D40E28DF645BB373ADAE5E39B2A539F98F48507192E9993DAFEDE4D30331E7912A944E0A9C203BD851C0C0D7DCBC672186F9DF652220BC26B85C327A81DE6656E5D73550FCD2EA1BA53552F; domain=.isomething.com; path=/
DEBUG [org.apache.http.headers] http-outgoing-4 << Connection: Keep-Alive
DEBUG [org.apache.http.headers] http-outgoing-4 << Keep-Alive: timeout=5, max=999
DEBUG [org.apache.http.headers] http-outgoing-4 << Server: Oracle-Application-Server-10g/10.1.2.3.0 Oracle-HTTP-Server OracleAS-Web-Cache-10g/10.1.2.3.2 (N;ecid=100569954162,0)
DEBUG [org.apache.http.headers] http-outgoing-4 << Content-Length: 5134
DEBUG [org.apache.http.headers] http-outgoing-4 << Date: Tue, 31 Mar 2015 13:06:53 GMT
DEBUG [org.apache.http.headers] http-outgoing-4 << Content-Location: /servlet/RepositoryServlet/cust_portal/!CUST_PORTAL.wwa_app_module.accept
DEBUG [org.apache.http.impl.execchain.MainClientExec] Connection can be kept alive for 5000 MILLISECONDS
DEBUG [org.apache.http.client.protocol.ResponseProcessCookies] Cookie accepted [SSO_TIMEOUT_ID="v1.0~83BA4EF3DA76C07B68FCC2530F599A0EC0C64F824C7AE3F72C95A8D07625F4915248DB9B7D40E28DF645BB373ADAE5E...", version:0, domain:isomething.com, path:/, expiry:null]
我为此挣扎了一段时间。。。太长了。几个小时!?无论如何,我有一个小包装器类,这样我就可以以“任何多部分形式”发送文件,只是我想要将文件(我将它作为原始字节[]发送,在我的情况下,我有一个上传控制器将其上传到另一个控制器,在这种情况下不需要解析文件)绑定到“file”属性发送
@Getter
public class MultipartMap {
private static final String GOT_NUTHIN_TO_MULTIPART_POST = "Got nuthin to multipart-post!!";
private final byte[] toPost;
public final String DEFAULT_FILENAME = "unknownFile";
private final String filename;
private Map<String, String> textParams = new HashMap<>();
public MultipartMap(byte[] data, String fileName, MultipartTextField... multipartTextField) {
this.toPost = data;
this.filename = StringUtils.hasContents(fileName) ? fileName : DEFAULT_FILENAME;
Arrays.stream(multipartTextField).forEach(param -> textParams.put(param.getFormName(), param.getFormValue()));
}
public void isSane() {
if (toPost == null || toPost.length == 0) {
throw new WrappedHttpClientException(GOT_NUTHIN_TO_MULTIPART_POST);
}
}
}
然后我有了一个很好的包装好的HttpClient,以我喜欢的方式执行这个多部分设置的post:
private static final String FILE = "file";
private static final String CONTENT_TYPE = "content-type";
..
multipartMap.isSane();
isMultiPartRequest = true;
final MultipartEntityBuilder multipartBuilderInner = MultipartEntityBuilder.create();
multipartBuilderInner.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartBuilderInner.addBinaryBody(
FILE,
multipartMap.getToPost(),
ContentType.DEFAULT_BINARY,
multipartMap.getFilename()
);
multipartMap.getTextParams().entrySet().stream().forEach(e -> {
multipartBuilderInner.addTextBody(e.getKey(), e.getValue(), ContentType.TEXT_PLAIN);
});
..
HttpPost request = new HttpPost(url);
request.setEntity(multipartBuilderInner.build());
..
if (isMultiPartRequest && req.getAllHeaders() != null) {
request.removeHeaders(CONTENT_TYPE); // this is IMPORTANT for multipart-requests!!
}
现在,正如ok2c上面所指出的——只要我没有绝对确定(你应该比这更小心,不管大小写,移除标题应该是匹配的任何东西,等等)内容类型不是设置的,我总是会得到臭名昭著的
"所需请求部分'xxx'不存在"
从我的控制器回来。然后,一旦我确保没有手动设置内容类型,事情就完美地运行了。只是作为参考,另一边的控制器看起来像
@PostMapping(path = "saveDocument", produces = "application/json; charset=utf-8", consumes = "multipart/form-data")
public ResponseEntity<String> saveDocument(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart(value = "filename", required = false) String filename,..
必需的=false只是因为我想自己处理这个400响应,而不是让Spring在我接触它之前拒绝请求。好吧,谢谢ok2c,你肯定得到了我的支持!
试着去掉这条线
httppost.setHeader("Content-Type", "multipart/form-data");
更新了
正如预期的那样,应用程序正在发送无效的Content-Type标头
[org.apache.http.headers] http-outgoing-5 >> Content-Type: multipart/form-data
请不要手动设置Content-Type
,让HttpClient根据请求中包含的HttpEntity
的属性为您生成它
不久前,我花了很多时间试图提交带有文件的多部分表单。最后通过添加边界来解决问题。据我所知,经过一些调试后,服务器无法识别没有它的部件。
String boundary = "---------------"+UUID.randomUUID().toString();
multipartEntityBuilder.setBoundary(boundary);
...
HttpPost request = new HttpPost(uriBuilder.build());
request.setHeader("Content-Type", ContentType.MULTIPART_FORM_DATA.getMimeType()+";boundary="+boundary);
...
multipartEntityBuilder.addBinaryBody("document[file]", dataBytes, ContentType.APPLICATION_OCTET_STREAM, name);
我想做的是用httpclient下载一个文件。目前我的代码如下。 我的下载URL如下所示:http://example.com/file/afz938f348dfa3 正如你可以看到没有扩展名的文件(至少在网址)然而,当我去一个正常的浏览器网址,它下载文件asdasdaasda.txt或asdasdasdsd.pdf(名称是不同的url和extenstion并不总是相同的,取决于我试图下载什么)。
我正在尝试上载文件,但无法工作: 有用信息:运行IIS Express(使用PHP5.3)-Windows 7 Professional 32位 代码: move_uploaded_file($_FILES[图像][名称],/图像/。$_FILES["Imagem"]["name"])或die("Error:".print_r($_FILES)); 它打印:数组([imagem]= 我确信路径是正
我正在使用CKEditor插件将图像上传到我的OpenShift应用程序,但该应用程序不会上传文件。它在本地运行良好,但我无法确定是什么导致了这个问题。它似乎找不到目录。 == {err:{[Error: ENOENT, open'/var/lib/openShift/57cdb2770c1e660d0b000003/app-root/runtime/repo/路由来/.../Public/上传/
我正在尝试上传一个图像。当我从本地主机上进行时,它工作得很好,但当我发布它时,它从服务器上抛出一个错误: 当我使用此代码时: 错误为: System.io.DirectoryNotFoundException:找不到路径“d:\inetpub\vhosts\xx.com\httpdocs\images\sections\developer\clientlogo\demo.png”的一部分。在sys
问题内容: 我想编写Java应用程序,它将使用PHP将文件上传到Apache服务器。Java代码使用Jakarta HttpClient库版本4.0 beta2: PHP文件非常简单: 阅读响应,我得到以下结果: 这样请求就成功了,我可以与服务器通信了,但是PHP没有注意到文件- 返回的方法和变量为空。我不知道为什么会这样。我已经跟踪了HTTP响应和请求,它们看起来还不错: 请求是: 和回应: 我
如果我尝试上载文档文件,则会出现以下错误“上载路径似乎无效”。我将路径替换为绝对路径,然后我也得到了这个错误。请告诉我如何解决这个问题`