繁体   English   中英

java servlet中的Apache Commons文件上传问题

[英]Apache Commons fileUpload problem in java servlet

我尝试使用 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);失败了

任何指针?

对不起,谢谢你:)

抱歉,我没有包括这些:

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

谢谢

从堆栈跟踪中可以明显看出,您在类的第 156 行取消引用的项目之一为空。 尽管我们在提供的代码段中没有行号,但看起来这仅在upload.parseRequest行(您自己也将其确定为失败部分)上才真正可能。

奇怪的是,这似乎只有在upload为空时才会发生 - 但从您给出的代码来看,这似乎是不可能的,因为它从构造函数中分配了一个非空值,仅几行就可以了,从那时起就发生了变化。

如果您可以附加调试器,那么逐步执行您的方法并检查对象值将是一个好主意。 否则,可能值得在该点之前放置一些 println 语句来验证哪些对象是空的,哪些是非空的。

消息The log message is null表示它正在抱怨以下内容:

log(Level.SEVERE, null, ex);

更好地使用:

log(Level.SEVERE, "Failed to parse upload request", ex);

我会推断upload在那时以某种方式为空。 您确定您提供的源代码和编译后的类文件是同一版本(例如,错误行指向不同的指令)?

我想您可以使用 IDE 调试您的应用程序并为 NullPointerException 创建断点。

更新:您能否展示一下内部 catch 块之后是什么? 你用list做什么? 我猜您忘记了如果没有上传文件并且您只是开始对其进行迭代,该列表可能会保持为空?

我怀疑记录器正在抛出 NullPointerException 因为震惊“日志消息为空”。

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

Log4J 处理程序之一(Glassfish 处理程序)正在优雅地处理空消息并打印“日志消息为空”,但其他一些 Log4J 处理程序也没有处理这种情况并抛出 NullPointerException。

这可以解释为什么您的堆栈跟踪是关于 NullPointerException 而不是关于您正在捕获的 FileUploadException。 我无法解释为什么 NullPointerException 堆栈跟踪的顶部是您的代码 (ProcessUploadItem.java:156),而不是获取堆栈帧的 Throwable 代码有时会被愚弄。

无论如何,我认为问题的关键, FileUploadException ex ,一旦 NullPointerException 触发就会丢失,因此没有关于导致您进入 catch 块的调试信息。

将正确的日志消息传递给记录器和/或 FileUploadException 以打印其消息和堆栈跟踪以进一步进行。

首先 - 粘贴更多!

您粘贴的语法无效。 你有一个悬空的 try 块,没有捕获或 finally ......我会错误地在此处粘贴更多信息而不是更少......粘贴整个方法并在第 156 行添加注释以表明它是哪个。

NPE 是什么意思?

正如其他人所提到的,堆栈跟踪是您方法中某处的空引用。 您尝试访问的对象之一(成员变量或使用.运算符的方法)为空。 我们可以从您的堆栈跟踪中推断出这一点,但没有意义的是您粘贴的代码。 我们需要更多来帮助解决这个问题。

编写单元测试以找出 API 调用

此外,在介绍 servlet 和日志 API 的复杂性之前,我会编写一个单元测试来学习如何使用这个 API。

您可以通过查看他们的Test Suite来了解他们如何测试 FileUpload API。 您可以重用他们的MockHttpServletRequest (尽管这确实是一个对象,而不是模拟对象)进行类似的测试。

注意:您可能希望返回并查看与 FileUpload jar 版本匹配的这些文件的版本。

调试指针

要调试,这是我要做的:

我会在堆栈跟踪顶部的方法中的第一行断点,并在逐步执行这些方法时查看本地监视变量。 一旦您找到并摆脱了NullPointerException ,请附加 FileUpload 源并进入它以确保您在此之后碰巧遇到不同的 FileUpload 特定异常时实际输入了该代码。

祝你好运!

问题不完整。

您使用的是哪个版本的 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>

在阅读DiskFileItemFactory的文档时,我注意到当一个文件被上传时,它会临时保存在系统的某个地方,默认目录是System.getProperty("java.io.tmpdir")返回的 Temp 目录。 你确定你有权限写入这个目录,如果没有,你可以通过调用factory.setRepository(java.io.File yourDir)来设置一个新的存储库/目录。

不确定这是否会有所帮助,但这只是一个建议。

要么上载在 processRequest 行上为空,要么您误算了行数。 你还没有发布整个方法,所以我们都只是猜测。

如果 processRequest 调用实际上与上传实例化那么接近,我猜你有某种后处理。 您正在编辑的代码可能不是您正在编译的代码。

你的表单提交是什么样的? 上面的代码看起来不错,并且反映了我所拥有的。

检查您的表单提交是否属于“多部分”类型,因此:

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

在客户端,您需要将表单编码设置为 multipart。 请参阅RFC1867

另请注意,如果在调用parseRequest()之前以任何方式处理/读取了请求数据,则parseRequest()将返回 null(请参阅 Apache Commons File Upload FAQ)

当你说“and it failed at files = upload.parseRequest(request)”时,你需要指定更多信息。 反正我会尽量回答你的问题。

查看 javadoc,您正在创建一个未初始化的 DiskFileItemFactory 对象。 您需要指定要存储文件的目录。 调用 setRepository() 或通过调用 DiskFileItemFactory(int, File) 创建您的工厂

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM