Groovy upload file

I am trying to write a file and video downloader in grails / groovy. So every time the user fills out a new form, the controller uploads the file and stores the file name along with other fields in the database. So here's 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 am getting this error: Error 500: Execution of action [save] controller [ctv.StreamController] threw exception: Cannot pass object " org.apache.catalina.core.ApplicationHttpRequest@19f46c5d " with class "org.apache.catalina.core. ApplicationHttpRequest "in class' org.springframework.web.multipart.MultipartHttpServletRequest" Servlets: rake URI: /ctv/grails/stream/save.dispatch exception message: Unable to pass an object " org.apache.catalina.core.ApplicationHttpRequest@19f46c5d " with class "org.apache.catalina.core.ApplicationHttpRequest" to class "org.springframework.web.multipart.MultipartHttpServletRequest" Called: cannot pass 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:

can someone make it clear who 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>

      

+3


source to share


4 answers


Reason for the error message

The problem with your code is that you are calling the request object in the wrong class. This is part of the error message that tells you the following:

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

So there you have it org.apache.catalina.core.ApplicationHttpRequest

, and you are trying to apply it to org.springframework.web.multipart.MultipartHttpServletRequest

, which cannot be executed.

The beauty of groovy (which the grail is written in) is that it is dynamically typed. So much of this casting is redundant anyway!

Try to replace these two lines

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

      

Wherein:

def uploadedFile = request.getFile( "myFile" )

      

But that won't solve your problem! It will just change the error message: '(

Root source of the problem and how did we end up with the wrong request class?



When thinking about why you have the wrong type of request to throw, you may have forgotten to include enctype="multipart/form-data"

forms in your action. It should probably look something like this:

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

      

A simple change to this might fix your problem, but I would remove the casting too.

Update: the real (?) Answer

In HTML (and GSP is used to create 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 (inner) looks like this:

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

      

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

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

      

+7


source


I think you might be over complicating this. All we do is

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

      



You will also want to check the mimeType.

+1


source


Another way to use the Grails file loader module. More details here http://grails.org/plugin/file-uploader . It has a robust interface and rich possibilities to make a really nice part of your application.

0


source


You get an exception

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

      

because you haven't added enctype

the form should look like

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

      

0


source







All Articles