Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

groovy upload file

Tags:

grails

groovy

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>
like image 659
cybertextron Avatar asked Jul 05 '26 13:07

cybertextron


2 Answers

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">
like image 167
David Avatar answered Jul 07 '26 03:07

David


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.

like image 43
chrislovecnm Avatar answered Jul 07 '26 03:07

chrislovecnm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!