如何读取内容处置标头的内容?

发布于 2024-12-04 22:57:54 字数 2552 浏览 1 评论 0原文

临时解决: InputStream 在 Apache FileUpload API 中关闭


我想读取 content-disposition 标头的内容,但 request.getHeader ("content-disposition") 始终返回 null 且 request.getHeader ("content-type") 只返回第一行,就像这样 multipart/form-data;边界=AaB03x

假设我收到以下标头:

Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="submit-name"

Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain

... contents of file1.txt ...
--AaB03x--

我想读取所有内容处置标头。如何?

谢谢。


EDIT1:我真正想解决的是当客户端发送超过最大大小的文件时的问题,因为当你调用 request.getPart ("something") 时,你的部分名称并不重要传递给它,因为即使请求不包含此参数名称,它总是会抛出 IllegalStateException。

示例:

Part part = request.getPart ("param");
String value = getValue (part);
if (value.equals ("1")){
    doSomethingWithFile1 (request.getPart ("file1"))
}else if (value.equals (2)){
    doSomethingWithFile2 (request.getPart ("file2"))
}

private String getValue (Part part) throws IOException{
    if (part == null) return null;

    BufferedReader in = null;
    try{
        in = new BufferedReader (new InputStreamReader (part.getInputStream (), request.getCharacterEncoding ()));
    }catch (UnsupportedEncodingException e){}

    StringBuilder value = new StringBuilder ();
    char[] buffer = new char[1024];
    for (int bytesRead; (bytesRead = in.read (buffer)) != -1;) {
        value.append (buffer, 0, bytesRead);
    }

    return value.toString ();
}

我不能这样做,因为如果客户端发送的文件超过最大大小,则第一次调用 getPart 将引发异常(请参阅 getPart() Javadoc),所以我不知道我有哪个文件已收到。

这就是为什么我想阅读内容处置标题。我想读取参数“param”以了解哪个文件引发了异常。


EDIT2:好吧,使用发布 Servlet 3.0 规范的 API,您无法控制前面的情况,因为如果文件抛出异常,您将无法读取文件字段名称。这是使用包装器的负面部分,因为很多功能消失了......此外,使用 FileUpload,您可以动态设置 MultipartConfig 注释。

如果文件超过最大文件大小,API 会抛出 FileSizeLimitExceededException 异常。该异常提供了2个方法来获取字段名和文件名。

但!!我的问题还没有解决,因为我想读取与文件一起以相同形式发送的另一个参数的值。(前面的“param”的值示例)


EDIT3:我正在研究这个。一旦我编写了代码,我就会在这里发布!

TEMPORARY SOLVED: InputStream closed in Apache FileUpload API


I want to read the content of the content-disposition header but request.getHeader ("content-disposition") always return null and request.getHeader ("content-type") only returns the first line, like this multipart/form-data; boundary=AaB03x.

Supose I receive the following header:

Content-Type: multipart/form-data; boundary=AaB03x

--AaB03x
Content-Disposition: form-data; name="submit-name"

Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain

... contents of file1.txt ...
--AaB03x--

I want to read all the content-disposition headers. How?

Thanks.


EDIT1: What I really want to solve is the problem when the client sends a file that exceeds the maximum size because when you call request.getPart ("something") it doesn't matter what part name you pass to it because it always will throw an IllegalStateException even if the request does not contain this parameter name.

Example:

Part part = request.getPart ("param");
String value = getValue (part);
if (value.equals ("1")){
    doSomethingWithFile1 (request.getPart ("file1"))
}else if (value.equals (2)){
    doSomethingWithFile2 (request.getPart ("file2"))
}

private String getValue (Part part) throws IOException{
    if (part == null) return null;

    BufferedReader in = null;
    try{
        in = new BufferedReader (new InputStreamReader (part.getInputStream (), request.getCharacterEncoding ()));
    }catch (UnsupportedEncodingException e){}

    StringBuilder value = new StringBuilder ();
    char[] buffer = new char[1024];
    for (int bytesRead; (bytesRead = in.read (buffer)) != -1;) {
        value.append (buffer, 0, bytesRead);
    }

    return value.toString ();
}

I can't do this because if the client sends a file that exceeds the max size the first call to getPart will throw the exception (see getPart() Javadoc), so I can't know which file I've received.

That's why I want to read the content-disposition headers. I want to read the parameter "param" to know which file has thrown the exception.


EDIT2: Well, with the API that publishes the Servlet 3.0 specification you can't control the previous case because if a file throws an exception you can't read the file field name. This is the negative part of using a wrapper because a lot of functionalities disappear... Also with FileUpload you can dynamically set the MultipartConfig annotation.

If the file exceeds the maximum file size the api throws a FileSizeLimitExceededException exception. The exception provides 2 methods to get the field name and the file name.

But!! my problem is not still solved because I want to read the value of another parameter sent together with the file in the same form. (the value of "param" in the previous example)


EDIT3: I'm working on this. As soon as I write the code I'll publish it here!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

别理我 2024-12-11 22:57:54

request.getHeader ("content-disposition") 在您的情况下将返回 null,因为 Content-Disposition 标头出现在 HTTP POST 正文中,因此需要对它们进行处理分别地。事实上,Content-Disposition只是一个有效的HTTP响应头。作为请求的一部分,它永远不会被视为标头。

您最好使用 Commons FileUpload 等文件上传库或 Servlet Spec 3.0 的内置文件上传功能来读取 Content-Disposition 标头(间接)。需要实现 Servlet Spec 3.0 所需的文件上传功能的 Java EE 6 容器通常在底层使用 Apache Commons FileUpload。

如果您出于某种正当原因想忽略这些库并自己读取标头,那么我建议您查看 FileUploadBase Apache Commons FileUpload 类。请注意,这些方法实际上是从与 HttpServletRequest 关联的 InputStream 中读取的,并且您不能两次读取该流。如果您想先读取代码中的 Content-Disposition 标头,然后使用 Apache Commons FileUpload 解析请求,则必须传递一个 ServletRequestWrapper 来包装将原始请求复制到 FileUpload API。相反的顺序还要求您创建原始请求的副本,并将包装此副本的 ServletRequestWrapper 传递给 FileUpload API。总的来说,这是一个糟糕的设计,因为在内存(或磁盘)中复制整个流只是为了读取请求主体两次是没有意义的。

request.getHeader ("content-disposition") will return null in your case, as the Content-Disposition headers appear in the HTTP POST body, thereby requiring them to be treated separately. In fact, Content-Disposition is only a valid HTTP response header. As part of a request, it will never be treated as a header.

You're better off using a file upload library like Commons FileUpload or the in-built file-upload features of the Servlet Spec 3.0 to read the Content-Disposition header (indirectly). Java EE 6 containers that are required to implement the file-upload functionality required of Servlet Spec 3.0, often use Apache Commons FileUpload under the hood.

If you want to ignore these libraries for some valid reason and instead read the headers yourself, then I would recommend looking at the parseHeaderLine and getParsedHeaders methods of the FileUploadBase class of Apache Commons FileUpload. Do note that these methods actually read from the InputStream associated with the HttpServletRequest, and you cannot read the stream twice. If you want to read the Content-Disposition header in your code first, and later use Apache Commons FileUpload to parse the request, you will have to pass a ServletRequestWrapper that wraps a copy if the original request to the FileUpload API. The reverse sequence also requires you create a copy of the original request and pass a ServletRequestWrapper wrapping this copy to the FileUpload API. Overall, this is poor design, as it makes no sense to replicate an entire stream in memory (or on disk) only to read the request body twice.

初吻给了烟 2024-12-11 22:57:54

尝试使用 part.getName()

这是一个示例。

HTML 文件:

<form action="UploadServlet" method="post" enctype="multipart/form-data">
    <input type="text" value="phu" name="info">
    <input type="file" name="file1"/> <input type="submit"/>
</form>

Servlet:

String field;

for (Part part : request.getParts()) {
    field = part.getName();
    if (field.equals("info")) {
        // Your code here
    } else if (field.equals("file1")) {
        // Your code here
    }
}

Try to use part.getName()

Here is a sample.

Html file:

<form action="UploadServlet" method="post" enctype="multipart/form-data">
    <input type="text" value="phu" name="info">
    <input type="file" name="file1"/> <input type="submit"/>
</form>

Servlet:

String field;

for (Part part : request.getParts()) {
    field = part.getName();
    if (field.equals("info")) {
        // Your code here
    } else if (field.equals("file1")) {
        // Your code here
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文