3

I'm trying to write a uploader for file and video in grails/groovy. So every time the user fills out a new form the controller uploads the file and saves the filename along with other fields into the database. So, here is the save procedure:

def save = {
        def streamInstance = new Stream(params)
        if(request){
            MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
            CommonsMultipartFile uploadedFile = (CommonsMultipartFile)mpr.getFile("myFile");
            if(!uploadedFile.empty){
                println "helloworld"
                println "Class: ${uploadedFile.class}"
                println "Name: ${uploadedFile.name}"
                println "OriginalFileName: ${uploadedFile.originalFilename}"
                println "Size: ${uploadedFile.size}"
                println "ContentType: ${uploadedFile.contentType}"
                /*
                //def webRootDir = servletContext.getRealPath("/")
                //def userDir = new File(webRootDir, "/files/${session.user.login}")
                //userDir.mkdirs()
                uploadedFile.transferTo(new File("/Users/philipperibeiro/ctv/ctv/web-app/files"))
                streamInstance.file = uploadedFile.originalFilename
                */
            }
            else{
                flash.message = "file cannot be empty"
            }
        }
        if(!streamInstance.hasErrors() && streamInstance.save(flush : true)){
            flash.message = "${message(code: 'default.created.message', args : [message(code: 'stream.label', default:'Stream'), streamInstance.id])}"
            redirect(action : "show", id : streamInstance.id)
        }
        else{
            render(view : "create", model : [streamInstance : streamInstance])
        }
    }

I'm getting this error: Error 500: Executing action [save] of controller [ctv.StreamController] caused exception: Cannot cast object 'org.apache.catalina.core.ApplicationHttpRequest@19f46c5d' with class 'org.apache.catalina.core.ApplicationHttpRequest' to class 'org.springframework.web.multipart.MultipartHttpServletRequest' Servlet: grails URI: /ctv/grails/stream/save.dispatch Exception Message: Cannot cast object 'org.apache.catalina.core.ApplicationHttpRequest@19f46c5d' with class 'org.apache.catalina.core.ApplicationHttpRequest' to class 'org.springframework.web.multipart.MultipartHttpServletRequest' Caused by: Cannot cast object 'org.apache.catalina.core.ApplicationHttpRequest@19f46c5d' with class 'org.apache.catalina.core.ApplicationHttpRequest' to class 'org.springframework.web.multipart.MultipartHttpServletRequest' Class: StreamController At Line: [22] Code Snippet:

could someone give a clue of who to fix it?

<%@ page import="ctv.Stream" %>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="layout" content="main" />
        <g:set var="entityName" value="${message(code: 'stream.label', default: 'Stream')}" />
        <title><g:message code="default.create.label" args="[entityName]" /></title>
        <jqfu:resources tmpl=”false” />
    </head>
    <body>
        <div class="nav">
            <span class="menuButton"><a class="home" href="${createLink(uri: '/')}"><g:message code="default.home.label"/></a></span>
            <span class="menuButton"><g:link class="list" action="list"><g:message code="default.list.label" args="[entityName]" /></g:link></span>
        </div>
        <div class="body">
            <h1><g:message code="default.create.label" args="[entityName]" /></h1>
            <g:if test="${flash.message}">
            <div class="message">${flash.message}</div>
            </g:if>
            <g:hasErrors bean="${streamInstance}">
            <div class="errors">
                <g:renderErrors bean="${streamInstance}" as="list" />
            </div>
            </g:hasErrors>
            <g:form action="save" >
                <div class="dialog">
                    <table>
                        <tbody>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="district"><g:message code="stream.district.label" default="District" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'district', 'errors')}">
                                    <g:select name="district.id" from="${ctv.District.list()}" optionKey="id" value="${streamInstance?.district?.id}"  />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="dateAdded"><g:message code="stream.dateAdded.label" default="Date Added" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'dateAdded', 'errors')}">
                                    <g:datePicker name="dateAdded" precision="day" value="${streamInstance?.dateAdded}"  />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="name"><g:message code="stream.name.label" default="Name" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'name', 'errors')}">
                                    <g:textField name="name" maxlength="30" value="${streamInstance?.name}" />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="description"><g:message code="stream.description.label" default="Description" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'description', 'errors')}">
                                    <g:textField name="description" maxlength="100" value="${streamInstance?.description}" />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="media"><g:message code="stream.media.label" default="Media" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'media', 'errors')}">
                                    <g:textField name="media" maxlength="30" value="${streamInstance?.media}" />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="file"><g:message code="stream.file.label" default="File" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'file', 'errors')}">
                                    <!--g:textField name="file" maxlength="30" value="${streamInstance?.file}" />-->
                                    <g:form action="save"  enctype="multipart/form-data">
                                        <input type="file" name="myFile" />
                                    </g:form>
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="logo"><g:message code="stream.logo.label" default="Logo" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'logo', 'errors')}">
                                    <g:textField name="logo" value="${streamInstance?.logo}" />
                                </td>
                            </tr>

                            <tr class="prop">
                                <td valign="top" class="name">
                                    <label for="published"><g:message code="stream.published.label" default="Published" /></label>
                                </td>
                                <td valign="top" class="value ${hasErrors(bean: streamInstance, field: 'published', 'errors')}">
                                    <g:checkBox name="published" value="${streamInstance?.published}" />
                                </td>
                            </tr>

                        </tbody>
                    </table>
                </div>
                <div class="buttons">
                    <span class="button"><g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" /></span>
                </div>
            </g:form>
        </div>
    </body>
</html>

4 Answers 4

8

The cause of the error message

The problem with your code is that you are casting the request object to the wrong class. This is the part of the error message that tells you this:

Cannot cast object 'org.apache.catalina.core.ApplicationHttpRequest@19f46c5d' with class 'org.apache.catalina.core.ApplicationHttpRequest' to class 'org.springframework.web.multipart.MultipartHttpServletRequest'

So you have an org.apache.catalina.core.ApplicationHttpRequest and you're trying to cast it to a org.springframework.web.multipart.MultipartHttpServletRequest which can't be done.

The beauty of groovy (which grails is written on) is that it is dynamically typed. So most of this casting is redundant anyway!

Try replacing these two lines

MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
CommonsMultipartFile uploadedFile = (CommonsMultipartFile)mpr.getFile("myFile");

With this:

def uploadedFile = request.getFile( "myFile" )

But this will not solve your problem! It will just change the error message you get :'(

The root source of the problem, and how did we end up with the wrong request class?

Thinking about why you have the wrong request type for the cast, you might have forgotten to include enctype="multipart/form-data" in your form action. It should probably look something like this:

<g:form action="save" method="post" enctype="multipart/form-data"> ... </g:form>

Just changing this might solve your problem, but I would definitely remove the casting too.

Update: the real(?) answer

In HTML (and GSPs are used to make HTML) you cannot have nested forms. One form cannot be inside another. Your GSP has two forms, the first looks like this:

<g:form action="save">

The second (the inside one) looks like this

<g:form action="save" enctype="multipart/form-data">

So you need to get rid of the inside one completely, and make sure the outside one (the only remaining one) looks like this:

<g:form action="save" method="post" enctype="multipart/form-data">
Sign up to request clarification or add additional context in comments.

9 Comments

I did modify my code as you suggested, and I add this to the form: <g:form action="save" method="post" enctype="multipart/form-data"> <input type="file" name="myFile" /> </g:form> Error 500: Executing action [save] of controller [ctv.StreamController] caused exception: groovy.lang.MissingMethodException: No signature of method: org.apache.catalina.core.ApplicationHttpRequest.getFile() is applicable for argument types: (java.lang.String) values: [myFile] Possible solutions: getXML(), getAt(java.lang.String), getAt(java.lang.String), getLocale(), getInfo(), recycle() Servlet: grails
the role problem is with request.getFile()
@philippe Ok, try this println "Request class: ${request.class}" straight after the if (request) { line. It will tell us what class the request is and we can go from there.
Request class: class org.apache.catalina.core.ApplicationHttpRequest
@philippe Are you getting this error when you upload the file, or just when you try and view the page? Also, please include the GSP code into your question as it might help us find the problem.
|
1

I think you may be over complicating this. All we are doing is

def image = request.getFile('image') // image is the parameter name 
def imageBytes = image.getBytes()

You will want to check the mimeType as well.

1 Comment

def image = request.getFile('image') the whole problem is with request.getFile('name')
0

Another way you can use Grails file upload plugin. See more information here http://grails.org/plugin/file-uploader. It has robust interface and provides rich abilities to make really nice part of your app.

Comments

0

You are getting the exception

groovy.lang.MissingMethodException:  No signature of method: 
  org.apache.catalina.core.ApplicationHttpRequest.getFile()

because you have not added enctype

the form should look like

<form action="action_name" method="POST" enctype="multipart/form-data">

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.