java 使用 HttpClient4 上传文件时设置标题“Content-Type”的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6212404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 14:51:46  来源:igfitidea点击:

Problem with setting header "Content-Type" in uploading file with HttpClient4

javafile-uploadhttpclient

提问by ljader

I'm trying to a upload file (or multiple files) to my servlet, which is using Apache file-upload to handle and get post-ed files.

我正在尝试将文件(或多个文件)上传到我的 servlet,它使用 Apache 文件上传来处理和获取发布的文件。

All is going well and the file is send and recieved, when I use the following code.

当我使用以下代码时,一切顺利,文件被发送和接收。

DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost("http://myservice.com/servlet");

MultipartEntity entity2 = new MultipartEntity();
FileBody fileBody = new FileBody(new File("C:/docOut.pdf"));
entity2.addPart("file", fileBody);
post.setEntity(entity2);

HttpResponse httpResponse = client.execute(post);
System.out.println(EntityUtils.toString(httpResponse.getEntity()));

But when I try to set my own "Content-Type" to recommended one (or the one only accepted with the Apache file-upload library) with uploading file:

但是,当我尝试将自己的“内容类型”设置为推荐的(或仅被 Apache 文件上传库接受的)并上传文件时:

post.addHeader("Content-Type", "multipart/form-data");

My servlet doesn't get any of files and throws an exeption:

我的 servlet 没有得到任何文件并抛出一个异常:

org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:931)
at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331)
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:349)
at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
at com.myservice.server.filerep.action.FileUploadFormAction.execute(FileUploadFormAction.java:54)
at com.myservice.server.filerep.web.FileRepServlet.doGet(FileRepServlet.java:34)
at com.myservice.server.filerep.web.FileRepServlet.doPost(FileRepServlet.java:41)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488)

I'm aware that POST requests with the uploading file shouldn't contain boundary "elements" in request to determine the order of uploaded byte chunks, but I thought HttpClient will add all the needed information to my request (similar as when I don't specify content-type).

我知道带有上传文件的 POST 请求不应该在请求中包含边界“元素”来确定上传字节块的顺序,但我认为 HttpClient 会将所有需要的信息添加到我的请求中(类似于我不t 指定内容类型)。

My questions are:

我的问题是:

  1. Why did adding "Content-Type" break my request? Shouldn't HttpClient add boundary elements to content-type defined by me?

  2. Should I explicity set "Content-Type" to my request or let the library handle it?

  3. If I can set Content-Typeexplicity could you provide a code snippet?

  4. If I can explicity set Content-Type why should I use and prefer "multipart/form-data" to "application/x-www-form-urlencoded" when it comes to POSTing to some forms?

  1. 为什么添加“Content-Type”会破坏我的请求?HttpClient 不应该向我定义的内容类型添加边界元素吗?

  2. 我应该明确地为我的请求设置“Content-Type”还是让图书馆处理它?

  3. 如果我可以Content-Type明确设置,你能提供一个代码片段吗?

  4. 如果我可以明确地设置 Content-Type 为什么我应该在发布到某些表单时使用“multipart/form-data”而不是“application/x-www-form-urlencoded”?

PS: I found somehow related questions, but not addressing my problem:

PS:我发现了某种相关的问题,但没有解决我的问题:

ContentType issue with commons-upload and httpcomponent client

Commons-upload 和 httpcomponent 客户端的 ContentType 问题

How can I See the content of a MultipartForm request?

如何查看 MultipartForm 请求的内容?

采纳答案by Buhake Sindi

If you have form data enctype, you must follow the rules as specified in RFC 2388. Data in multipart message are treated as entity so each entity must have a header (with Content-Disposition, Content-Type, etc.) and a boundary.

如果您有表单数据 enctype,则必须遵循RFC 2388 中指定的规则。数据在多部分消息被视为实体,以便每个实体必须有一个头部(Content-DispositionContent-Type等)和的边界。

As to answer question 1, the RFC states:

关于回答问题 1,RFC 指出:

As with all multipart MIME types, each part has an optional "Content-Type", which defaults to text/plain.

与所有多部分 MIME 类型一样,每个部分都有一个可选的“Content-Type”,默认为 text/plain。

For 2), As mentioned, every multipart message must have an header, so you have to specify your Content-Type (if you're not fully using HttpClient library features).

对于 2),如前所述,每个多部分消息都必须有一个标头,因此您必须指定 Content-Type(如果您没有完全使用 HttpClient 库功能)。

For 3) and 4) RFC states:

对于 3) 和 4) RFC 状态:

If multiple files are to be returned as the result of a single form entry, they should be represented as a "multipart/mixed" part embedded within the "multipart/form-data".

如果将多个文件作为单个表单条目的结果返回,则它们应表示为嵌入在“multipart/form-data”中的“multipart/mixed”部分。

Hope this helps.

希望这可以帮助。

回答by Will

to fedd/ the class which inserts randomly generated boundary is HttpClient, not HttpPost. so you should look at methods for HttpClient

对于 fedd/ 插入随机生成边界的类是 HttpClient,而不是 HttpPost。所以你应该看看 HttpClient 的方法