为什么 servlet 在多部分请求中找不到 FileItem?

发布于 2024-12-25 10:50:23 字数 4213 浏览 0 评论 0 原文

我编写了一个 Servlet,它使用 Apache commons 文件上传库来处理文件上传。以下是一些代码:

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    if (isMultipart) {
        try {
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();

            // Set size threshold for storing upload
            fileItemFactory.setSizeThreshold(1 * 1024 * 50); // 50 KB

            // Set temporary directory to store uploaded files above threshold size
            fileItemFactory.setRepository(new File(TEMP_DIRECTORY));

            ServletFileUpload upload = new ServletFileUpload(fileItemFactory);

            //HashMap<String, String> params = new HashMap<String, String>();


            FileItemIterator iterator = upload.getItemIterator(request);
            upload.setSizeMax(REQUEST_MAX_SIZE);

            List items = upload.parseRequest(request);
            Iterator it = items.iterator();

            while (it.hasNext()) {
                FileItem item = (FileItem) it.next();

                if(item.isFormField()) {

                } else {
                    String contentType = item.getContentType();
                    String fileName = item.getName();
                    String fieldName = item.getFieldName();
                    boolean isInMemory = item.isInMemory();
                    long sizeInBytes = item.getSize();
                    File uploadedFile = new File(PATH + "new_audio1.amr");

                    item.write(uploadedFile);

                    System.out.println("Field: " + fieldName);
                    System.out.println("File name: " + fileName);
                    System.out.println("Size: " + sizeInBytes);
                    System.out.println("Is in memory:" + isInMemory);
                }
            }

        } catch (Exception ex) {
            throw new ServletException(ex);
        }
    } else {
        throw new ServletException();
    }

由于某种原因,我无法理解列表“项目”是空的,因此我无法获取上传的文件。

对于上传本身,我编写了一些java代码:

File audioFile = new File("C:\\Users\\Soto\\Desktop\\test recording.amr");

    String url = "http://localhost:8080/AudioFileUpload/UploadServlet";
    String charset = "UTF-8";

    // random values
    String latitude = "145";
    String longitude = "132";
    String speed = "0";


    String query;
    try {
        query = String.format("latitude=%s&longitude=%s&speed=%s", URLEncoder.encode(latitude, charset), URLEncoder.encode(longitude, charset), URLEncoder.encode(speed, charset));
    } catch (UnsupportedEncodingException e) {
        query = String.format("latitude=%s&longitude=%s&speed=%s", latitude, longitude, speed);
    }

    HttpClient httpClient = new DefaultHttpClient();
    httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    HttpPost httpPost = new HttpPost(url + "?" + query);

    MultipartEntity mpEntity = new MultipartEntity();
    ContentBody cbFile = new FileBody(audioFile, "audio/AMR");
    mpEntity.addPart("audioFile", cbFile);

    httpPost.setEntity(mpEntity);

    HttpResponse response = null;
    try {
        response = httpClient.execute(httpPost);
        HttpEntity responseEntity = response.getEntity();
        System.out.println(response.getStatusLine());

        if(responseEntity != null) 
            System.out.println(EntityUtils.toString(responseEntity));

        if(responseEntity != null) {
            EntityUtils.consume(responseEntity);
        }

        httpClient.getConnectionManager().shutdown();

    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

我感觉文件正在正确附加和上传。 我还尝试通过 HTML 和 multipart/form-data post 请求来完成此操作,但仍然找不到该文件。

我做错了什么?

编辑: 我删除了 doPost() 开头的行以及 if 语句:

ServletFileUpload.isMultipartContent(request);

然后上传工作正常。此方法是否可能消耗请求的“输入/输出/无论是什么”流?

谢谢

I've written a Servlet that handles file uploads using the Apache commons file upload library. Here is some of the code:

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    if (isMultipart) {
        try {
            DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();

            // Set size threshold for storing upload
            fileItemFactory.setSizeThreshold(1 * 1024 * 50); // 50 KB

            // Set temporary directory to store uploaded files above threshold size
            fileItemFactory.setRepository(new File(TEMP_DIRECTORY));

            ServletFileUpload upload = new ServletFileUpload(fileItemFactory);

            //HashMap<String, String> params = new HashMap<String, String>();


            FileItemIterator iterator = upload.getItemIterator(request);
            upload.setSizeMax(REQUEST_MAX_SIZE);

            List items = upload.parseRequest(request);
            Iterator it = items.iterator();

            while (it.hasNext()) {
                FileItem item = (FileItem) it.next();

                if(item.isFormField()) {

                } else {
                    String contentType = item.getContentType();
                    String fileName = item.getName();
                    String fieldName = item.getFieldName();
                    boolean isInMemory = item.isInMemory();
                    long sizeInBytes = item.getSize();
                    File uploadedFile = new File(PATH + "new_audio1.amr");

                    item.write(uploadedFile);

                    System.out.println("Field: " + fieldName);
                    System.out.println("File name: " + fileName);
                    System.out.println("Size: " + sizeInBytes);
                    System.out.println("Is in memory:" + isInMemory);
                }
            }

        } catch (Exception ex) {
            throw new ServletException(ex);
        }
    } else {
        throw new ServletException();
    }

For some reason that escapes me the List 'items' is empty so I can't grab the uploaded file.

For the upload itself, I've written some java code:

File audioFile = new File("C:\\Users\\Soto\\Desktop\\test recording.amr");

    String url = "http://localhost:8080/AudioFileUpload/UploadServlet";
    String charset = "UTF-8";

    // random values
    String latitude = "145";
    String longitude = "132";
    String speed = "0";


    String query;
    try {
        query = String.format("latitude=%s&longitude=%s&speed=%s", URLEncoder.encode(latitude, charset), URLEncoder.encode(longitude, charset), URLEncoder.encode(speed, charset));
    } catch (UnsupportedEncodingException e) {
        query = String.format("latitude=%s&longitude=%s&speed=%s", latitude, longitude, speed);
    }

    HttpClient httpClient = new DefaultHttpClient();
    httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    HttpPost httpPost = new HttpPost(url + "?" + query);

    MultipartEntity mpEntity = new MultipartEntity();
    ContentBody cbFile = new FileBody(audioFile, "audio/AMR");
    mpEntity.addPart("audioFile", cbFile);

    httpPost.setEntity(mpEntity);

    HttpResponse response = null;
    try {
        response = httpClient.execute(httpPost);
        HttpEntity responseEntity = response.getEntity();
        System.out.println(response.getStatusLine());

        if(responseEntity != null) 
            System.out.println(EntityUtils.toString(responseEntity));

        if(responseEntity != null) {
            EntityUtils.consume(responseEntity);
        }

        httpClient.getConnectionManager().shutdown();

    } catch (ClientProtocolException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

It feels to me like the file is being attached and uploaded correctly.
I also tried doing it through HTML with a multipart/form-data post request, but the file still wasn't found.

What am I doing wrong?

EDIT:
I removed the line at the beginning of the doPost() along with the if statement:

ServletFileUpload.isMultipartContent(request);

And then the upload worked correctly. Is it possible that this method consumes the request's 'input/output/whatever it is' stream?

Thanks

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

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

发布评论

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

评论(2

短暂陪伴 2025-01-01 10:50:23

编辑:我删除了 doPost() 开头的行以及 if 语句:

ServletFileUpload.isMultipartContent(请求);

然后上传就正常了。此方法是否有可能消耗请求的“输入/输出/无论是什么”流?

这很奇怪。该方法所做的只是检查请求方法是否等于 POST 以及 Content-Type 标头是否以 multipart/ 开头。以下是当前最新 Commons FileUpload API 版本的源代码摘录(多年来没有太大变化):

public static final boolean isMultipartContent(
        HttpServletRequest request) {
    if (!"post".equals(request.getMethod().toLowerCase())) {
        return false;
    }
    String contentType = request.getContentType();
    if (contentType == null) {
        return false;
    }
    if (contentType.toLowerCase().startsWith(MULTIPART)) {
        return true;
    }
    return false;
}

你看,没有什么令人震惊的。

也许您正在使用一个非常晦涩/有缺陷的 servlet 容器,它显示了一个错误,当您调用 request.getMethod()getContentType() 时,请求正文将隐式被消耗。 。

EDIT: I removed the line at the beginning of the doPost() along with the if statement:

ServletFileUpload.isMultipartContent(request);

And then the upload worked correctly. Is it possible that this method consumes the request's 'input/output/whatever it is' stream?

This is strange. All that method does is checking if the request method equals to POST and if the Content-Type header starts with multipart/. Here's an extract of the source of the currently latest Commons FileUpload API version (which hasn't changed much across years):

public static final boolean isMultipartContent(
        HttpServletRequest request) {
    if (!"post".equals(request.getMethod().toLowerCase())) {
        return false;
    }
    String contentType = request.getContentType();
    if (contentType == null) {
        return false;
    }
    if (contentType.toLowerCase().startsWith(MULTIPART)) {
        return true;
    }
    return false;
}

You see, nothing shocking.

Perhaps you're using a very obscure/buggy servlet container which manifests a bug that the request body will implicitly be consumed when you call request.getMethod() or getContentType().

可是我不能没有你 2025-01-01 10:50:23

我认为您忘记设置内容类型?使用 fiddler 查看线路上的内容

为什么不使用 MultiPartPostData

http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/methods/MultipartPostMethod.html

I think you forgot to set content type? Use fiddler to see whats gking on the wire

Why dont you use MultiPartPostData

http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/methods/MultipartPostMethod.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文