Проблема Apache Commons fileUpload в сервлете Java - PullRequest
1 голос
/ 05 июня 2009

Я пытался сделать это с помощью Apache Commons FileUpload:

protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException {

    PrintWriter out = null;

    try {

        response.setContentType("text/html;charset=UTF-8");
        //MultipartFormDataRequest dataRequest = new MultipartFormDataRequest(request);
        //get uploaded files
        FileItemFactory factory = new DiskFileItemFactory();
        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        List files = null;
        try {
            files = upload.parseRequest(request);
        } catch (FileUploadException ex) {
            Logger.getLogger(ProcessUploadItem.class.getName()).log(Level.SEVERE, null, ex);
    }
}

и не удалось на files = upload.parseRequest(request);

какие-нибудь указатели?

извините и спасибо :) 1009 *

Извините, я не включил это:

The log message is null.
java.lang.NullPointerException
    at web.ProcessUploadItem.processRequest(ProcessUploadItem.java:156)
    at web.ProcessUploadItem.doPost(ProcessUploadItem.java:193)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
    at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:290)
    at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
    at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
    at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
java.lang.NullPointerException
    at web.ProcessUploadItem.processRequest(ProcessUploadItem.java:156)
    at web.ProcessUploadItem.doPost(ProcessUploadItem.java:193)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:738)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
    at org.apache.catalina.core.ApplicationFilterChain.servletService(ApplicationFilterChain.java:411)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:290)
    at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:271)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:202)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:94)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:206)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:150)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:632)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:577)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:571)
    at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1080)
    at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:272)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:637)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:568)
    at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:813)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:263)
    at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.doTask(DefaultReadTask.java:214)
    at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:265)
    at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)

Я использую Glassfish

Спасибо

Ответы [ 10 ]

2 голосов
/ 17 июня 2009

Из трассировки стека ясно, что один из элементов, которые вы разыменовали в строке 156 вашего класса, является нулевым. Хотя в предоставленном фрагменте нет номеров строк, похоже, что это действительно возможно только в строке upload.parseRequest (которую вы также определили как неисправную часть).

Как ни странно, похоже, что это может произойти, только если upload равно нулю - но из кода, который вы дали, это кажется невозможным, поскольку ему присваивается ненулевое значение из конструктора всего на несколько строк вверх, и теперь он изменился с тех пор .

Если вы можете присоединить отладчик, тогда было бы неплохо пройтись по вашему методу и проверить значения объекта. В противном случае, возможно, стоит добавить несколько операторов println непосредственно перед этой точкой, чтобы проверить, какие объекты являются нулевыми, а какие ненулевыми.

2 голосов
/ 21 июня 2009

Сообщение The log message is null указывает, что оно жалуется на следующее:

log(Level.SEVERE, null, ex);

Лучше использовать:

log(Level.SEVERE, "Failed to parse upload request", ex);
1 голос
/ 20 июня 2009

Сначала - вставь больше!

Синтаксис, который вы вставили, неверен. У вас есть свисающий блок try без улова или, наконец, ... Я бы ошибся, вставив сюда больше информации, чем меньше ... Вставьте весь метод и поместите комментарий в строку 156, чтобы указать, что это.

Что означает NPE?

Как уже упоминали другие, трассировка стека является нулевой разыменовкой внутри вашего метода где-то. Один из объектов, к которым вы пытались получить доступ к чему-либо (переменная-член или метод, использующий оператор .), является нулевым. Мы можем вывести это из вашей трассировки стека, но не имеет смысла код, который вы вставили с ним. Нам нужно больше, чтобы помочь разобраться.

Напишите модульный тест для определения вызовов API

Кроме того, я бы написал модульный тест , чтобы узнать, как работать с этим API, прежде чем представлять сложность API сервлетов и журналирования.

Вы можете увидеть, как они тестировали API FileUpload, взглянув на их Test Suite . Вы можете повторно использовать их MockHttpServletRequest (хотя это действительно поддельный объект, а не mock объект) для аналогичного тестирования.

Примечание. Возможно, вы захотите вернуться назад и посмотреть версии этих файлов, которые соответствуют версии вашего файла FileUpload.

Указатели отладки

Для отладки вот что я сделаю:

Я бы остановил первую строку в методе в верхней части вашей трассировки стека и посмотрел на локальные переменные наблюдения, пока я шагал по методам. Как только вы найдете и избавитесь от NullPointerException, присоедините источник FileUpload и войдите в него, чтобы убедиться, что вы действительно вводите этот код, если после этого у вас получится другое исключение, специфичное для FileUpload.

Удачи!

1 голос
/ 19 июня 2009

Я подозреваю, что регистратор создает исключение NullPointerException, потому что shock"сообщение журнала пусто".

Logger.getLogger(...).log(Level.SEVERE, >>>null<<<, ex);

Один из обработчиков Log4J (Glassfish) изящно обрабатывает нулевое сообщение и печатает «Сообщение журнала пусто», но некоторые другие обработчики Log4J также не обрабатывают ситуацию и выдают исключение NullPointerException.

Это может объяснить, почему ваши трассировки стека относятся к исключению NullPointerException, а не к FileUploadException, который вы перехватываете. Я не могу объяснить, почему вершиной трассировки стека NullPointerException является ваш код (ProcessUploadItem.java:156), отличный от Throwable-кода, который получает фреймы стека, который иногда можно обмануть.

Несмотря на это, я думаю, что ключ к проблеме, FileUploadException ex , теряется, как только срабатывает исключение NullPointerException, поэтому нет никакой отладочной информации о том, что заставляет вас войти в блок catch.

Передайте соответствующее сообщение журнала в регистратор и / или FileUploadException, чтобы напечатать его сообщение и трассировку стека, чтобы продолжить работу.

1 голос
/ 17 июня 2009

Я бы сделал вывод, что upload как-то равно нулю в этой точке. Вы уверены, что предоставленный вами исходный код и скомпилированный файл класса имеют одинаковую версию (например, строка ошибки указывает на другую инструкцию)?

Полагаю, вы могли бы отладить ваше приложение с помощью IDE и создать точку останова для NullPointerException.

Обновление: Не могли бы вы показать, что находится после внутреннего блока? Что вы делаете с list? Я полагаю, вы забыли, что список может остаться нулевым, если файл не загружен, и вы просто начинаете его перебирать?

0 голосов
/ 23 июня 2009

Либо загрузка пуста в строке processRequest, либо вы пропустили строки. Вы еще не опубликовали весь метод, поэтому мы все просто догадываемся.

Если вызов processRequest действительно близок к экземпляру загрузки, я думаю, у вас есть какая-то постобработка. Код, который вы редактируете, может не совпадать с кодом, который вы компилируете.

0 голосов
/ 18 июня 2009

При чтении документации для DiskFileItemFactory я заметил, что при загрузке файла он временно сохраняется где-то в системе, и каталогом по умолчанию для этого является каталог Temp, возвращаемый System.getProperty("java.io.tmpdir"). Вы уверены, что у вас есть права на запись в этот каталог, а если нет, то, возможно, вы можете установить новый репозиторий / каталог, вызвав factory.setRepository(java.io.File yourDir).

Не уверен, поможет ли это, но это всего лишь предложение.

0 голосов
/ 17 июня 2009

Вопрос не завершен.

Какую версию commons-upload вы используете? Ваша форма использует multipart / form-data MIME-тип в качестве типа кодировки?

Вот пример:

<form action="/uploadServlet" enctype="multipart/form-data" method="post">
  <input type="file" name="file" size="40">
  <input type="submit" value="Send">
</form>
0 голосов
/ 05 июня 2009

Как выглядит ваше заполнение формы? Приведенный выше код выглядит хорошо и отражает то, что у меня есть.

Проверьте, что ваша форма отправки имеет тип 'multipart', таким образом:

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

На стороне клиента необходимо установить кодировку формы в multipart. См. RFC1867 .

Также обратите внимание, что parseRequest() вернет ноль, если данные запроса были обработаны / прочитаны любым способом до вызова parseRequest() (см. FAQ по загрузке файлов Apache Commons)

0 голосов
/ 05 июня 2009

Вам нужно указать дополнительную информацию, когда вы говорите «и это не удалось в files = upload.parseRequest (request)». В любом случае, я постараюсь ответить на ваш вопрос.

Глядя на javadoc, вы создаете неинициализированный объект DiskFileItemFactory. Вам необходимо указать каталог, в котором вы хотите хранить файлы. Вызовите setRepository () или создайте свою фабрику, вызвав DiskFileItemFactory (int, File)

...