Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails - Exception when stopping/cancelling an upload

I have a very basic upload action in my controller. It looks something like the action below. It works great. The only problem I'm seeing is when a user cancels an upload (or hits stop on their browser). I am able to recover correctly, but not before seeing an uncaught exception in my logs. The exception is listed below. Any help or feedback on how to correctly catch the uncaught exception here would be appreciated. Seems like it's happening somewhere between the client and the controller action since the exception is being displayed but none of the log messages in the action are showing up.

def upload = {
    def f = null
    try {
        f = request.getFile('assetFile')
        if(!f || f.empty) {
            log.warn "File is empty"
            render(view:'upload')
            return
        }
    } catch (Exception e) {
        log.warn "Caught exception:", e
        render(view:'upload')
        return
    }
}

Exception is:

 2010-08-06 15:33:22,826 ERROR [TP-Processor8] filter.UrlMappingsFilter - Error when matching URL mapping [/(*)/(*)?/(*)?]:Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
    org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
            at org.jsecurity.web.servlet.JSecurityFilter.doFilterInternal(JSecurityFilter.java:384)
            at org.jsecurity.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:183)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
            at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
            at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
            at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
            at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
            at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
            at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
            at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
            at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
            at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:200)
            at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
            at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:775)
            at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:704)
            at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:897)
            at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
            at java.lang.Thread.run(Thread.java:619)
    Caused by: org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
            at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:367)
            at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
            ... 25 more
    Caused by: org.apache.commons.fileupload.MultipartStream$MalformedStreamException: Stream ended unexpectedly
            at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:983)
            at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:887)
            at java.io.InputStream.read(InputStream.java:85)
            at org.apache.commons.fileupload.util.Streams.copy(Streams.java:94)
            at org.apache.commons.fileupload.util.Streams.copy(Streams.java:64)
            at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:362)
            ... 26 more 
like image 964
user415217 Avatar asked Oct 26 '22 09:10

user415217


2 Answers

I'm terribly late on this, but I just ran into the same problem today and resolved it by adding a servlet filter (I also tried a Grails filter, but the exception is thrown prior to hitting it).

First you need to create a web.xml in your project...

grails install-templates

Add a filter to web.xml (make sure not to put the filter-mapping before any other filters)...

<filter>
    <filter-name>upload</filter-name>
    <filter-class>com.myProject.UploadFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>upload</filter-name>
    <url-pattern>/media/uploadMediaAsset/*</url-pattern>
</filter-mapping>

Create the filter class...

package com.myProject

import javax.servlet.*

import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory

import org.springframework.web.multipart.MultipartException

public class UploadFilter implements Filter {

private Log log = LogFactory.getLog(getClass())

public void init(FilterConfig filterConfig) throws ServletException { /* Do nothing */ }

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {

    log.debug 'Making sure file upload gets here.'

    try {
        chain.doFilter(request, response)
    } catch (MultipartException mpE) {
        log.error mpE
    }
}

public void destroy() { /* Do nothing */ }

}

like image 129
trotttrotttrott Avatar answered Nov 16 '22 13:11

trotttrotttrott


Late response. I was actually able to find the solution for anyone still working on this problem. See http://brainflush.wordpress.com/2008/12/04/how-to-gracefully-recover-from-file-upload-errors-in-grails/.

like image 35
user415217 Avatar answered Nov 16 '22 14:11

user415217