Grails上传图片

时间:2011-12-01 12:24:10

标签: grails file-upload

我正在尝试上传图片,并将其保存在数据库中。 如果我执行以下操作,则会收到此错误:

无法转换类型

的属性值
  

org.springframework.web.multipart.commons.CommonsMultipartFile to   属性picture1所需的类型java.lang.Byte [];嵌套异常   是java.lang.IllegalArgumentException:无法转换类型的值   [org.springframework.web.multipart.commons.CommonsMultipartFile]来   属性picture1 [0]的必需类型[java.lang.Byte]:   属性编辑器   [org.springframework.beans.propertyeditors.CustomNumberEditor]   返回不合适的价值

如果我这样做:

if(request instanceof MultipartHttpServletRequest){
    MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
    CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("picture1");
}

我收到此错误:

  

执行控制器[com.testapp.RequestController]的动作[保存]   引起异常:无法投射对象'   org.springframework.web.multipart.commons.CommonsMultipartFile@34ae1f02'   与班级   'org.springframework.web.multipart.commons.CommonsMultipartFile'来   class'java.lang.Byte'

我该怎么做才能使这项工作?

package com.testapp

class Request{  
    String requestID
    Date dateCreated
    String subject
    String startedBy 
    String description
    String status
    String priority 
    Productline productline
    Topic topic
    Subtopic subtopic
    String company
    Byte [] picture1
    Byte [] picture2
    Byte [] picture3
    String acceptedBy 


    static constraints = {
        requestID(blank:true,nullable:true)
        dateCreated(blank:true,nullable:true)
        subject()
        description(maxSize:5000)
        status (blank:true,nullable:true)
        priority(inList:["Normal","Urgent","Not urgent"])
        productline(blank:true,nullable:true)
        topic(blank:true,nullable:true)
        subtopic(blank:true,nullable:true)
        company(blank:true,nullable:true)
        startedBy(blank:true,nullable:true)
        acceptedBy(blank:true,nullable:true)
        picture1(blank:true,nullable:true)
        picture2(blank:true,nullable:true)
        picture3(blank:true,nullable:true)
    }

}

GSP:

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta name="layout" content="main" />
    <g:set var="entityName" value="${message(code: 'request.label', default: 'Request')}" />
    <title><g:message code="New request" args="[entityName]" /></title>
</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="userList"><g:message code="Lista zahteva" `args="[entityName]" /></g:link></span>`
    </div>
<div class="body">
        <h1><g:message code="New request" args="[entityName]" /></h1>
        <g:if test="${flash.message}">
        <div class="message">${flash.message}</div>
        </g:if>
        <g:hasErrors bean="${requestInstance}">
        <div class="errors">
            <g:renderErrors bean="${requestInstance}" as="list" />
        </div>
</g:hasErrors>
        <g:form action="save" method="post" enctype="multipart/form-data">
            <div class="dialog">
                <table>
                    <tbody>

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

                        <tr class="prop">
                            <td valign="top" class="name">
                                <label for="description"><g:message code="request.description.label" default="Opis" /></label>
                            </td>
                            <td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'description', 'errors')}">
                                <g:textArea name="description" cols="40" rows="5" value="${requestInstance?.description}" />
                            </td>
                        </tr>
                        <tr>
                            <td valign="top" class="name">
                                <label for="picture1"><g:message code="request.picture1.label" default="Printscreen" /></label>
                            </td>           

                            <td valign="top" class="value">
                                <input type="file" id="picture1" name="picture1"/>
                            </td>
                        </tr>

                        <tr class="prop">
                            <td valign="top" class="name">
                                <label for="priority"><g:message code="request.priority.label" default="Priority" /></label>
                            </td>
                            <td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'status', 'errors')}">
                                <g:select name="priority" from="${requestInstance.constraints.priority.inList}" value="${requestInstance?.priority}" valueMessagePrefix="request.priority"  />
                            </td>
                        </tr>



                        <tr class="prop">
                            <td valign="top" class="name">
                                <label for="productline"><g:message code="request.productline.label" default="Productline" /></label>
                            </td>
                            <td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'productline', 'errors')}">
                                <g:select name="productline.id" from="${com.testapp.Productline.list()}" optionKey="id" value="${requestInstance?.productline?.id}"  />
                            </td>
                        </tr>

                        <tr class="prop">
                            <td valign="top" class="name">
                                <label for="topic"><g:message code="request.topic.label" default="Topic" /></label>
                            </td>
                            <td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'topic', 'errors')}">
                                <g:select name="topic.id" from="${com.testapp.Topic.list()}" optionKey="id" value="${requestInstance?.topic?.id}"  />
                            </td>
                        </tr>

                        <tr class="prop">
                            <td valign="top" class="name">
                                <label for="subtopic"><g:message code="request.subtopic.label" default="Subtopic" /></label>
                            </td>
                            <td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'subtopic', 'errors')}">
                                <g:select name="subtopic.id" from="${com.testapp.Subtopic.list()}" optionKey="id" value="${requestInstance?.subtopic?.id}"  />
                            </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>

控制器:

def save = {
    def requestInstance = new Request(params)
    def requestNumberInstance = new RequestNumber()
            def upPic1 = request.getFile('picture1') 

    def lastReqNum = RequestNumber.find("from RequestNumber ORDER BY requestNumber desc")
    if(lastReqNum){
        requestNumberInstance.requestNumber = lastReqNum.requestNumber + 1
    }
    else{
        requestNumberInstance.requestNumber = 110000
    }


    requestInstance.requestID = "CSC" + requestNumberInstance.requestNumber
    def currentUserContact =  Contact.findByUser(springSecurityService.getCurrentUser())
    requestInstance.startedBy = currentUserContact.realname
    requestInstance.company = currentUserContact.company
    requestInstance.status = "Opened"
    requestInstance.acceptedBy = "Not yet accepted"
            requestInstance.picture1 = upPic1


    if(requestNumberInstance.save()){



        if (requestInstance.save()) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'request.label', default: 'Request'), requestInstance.id])}"
            redirect(action: "show", id: requestInstance.id)
        }
        else {
            render(view: "create", model: [requestInstance: requestInstance])
        }
    }
    else{
         render(view: "create", model: [requestInstance: requestInstance])
    }
}

请不要介意意大利面条代码。我只想尝试一些基本概念。我稍后会清楚。

简化示例:

def save = {
    def requestInstance = new Request(params)
    def requestNumberInstance = new RequestNumber()

    if(requestInstance.validate() && requestInstance.save(flush: true)){
        println "Saved successfully with ${requestInstance.picture1.length} bytes"
    } 
    else {
        println "Save failed"
    }

3 个答案:

答案 0 :(得分:6)

问题修改后更新

错误可能是由此引起的:

def upPic1 = request.getFile('picture1') 
...
requestInstance.picture1 = upPic1

request.getFile()正在返回一个MultipartFile,您正在尝试将其分配到Byte[]字段。考虑到我的小例子(下面),你甚至不需要尝试进行这项任务。 def requestInstance = new Request(params)将自动绑定byte[]


上传的文件会自动绑定到byte[]字段。这是一个有效的例子:

域:grails-app/domain/my/Example.groovy

package my

class Example {
    byte[] file
}

控制器:grails-app/controllers/my/ExampleController.groovy

package my

class ExampleController {
    def create = { }

    def save = {
        def example = new Example(params)
        if(example.validate() && example.save(flush: true)) {
            println "Saved successfully with ${example.file.length} bytes"
        } else {
            println "Save failed"
        }

        redirect(action: 'create')
    }
}

GSP:grails-app/views/example/create.gsp

<!DOCTYPE html>
<html>
  <body>
    <g:uploadForm action="save">
      <input type="file" name="file"/>
      <g:submitButton name="submit"/>
    </g:uploadForm>
  </body>
</html>

当我使用GSP表单上传一个小文件时,我看到以下控制台输出:

Saved successfully with 23 bytes

<强>建议

  • 尝试使用Grails数据绑定来保存文件内容。
  • 确保您的表单为<g:uploadForm>enctype="multipart/form-data" if you're using a vanilla`。
  • 确保使用域构造函数domain.propertiesbindData()绑定参数。

答案 1 :(得分:3)

我猜你的打字搞砸了。

如果您只是这样做会发生什么:

def f = request.getFile('myFile')

如手册中所述。如果你想要强类型,它应该是MultiPartfile,而不是CommonsMultiPartFile,据我记得(你从请求对象得到它)。

这是您正在使用的界面:http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/multipart/MultipartFile.html

您的相关方法应该是getBytes()。

编辑已修改的问题:

正如我所说,你想要getBytes(),你试图将一个MultiPartFile推入一个字节数组中,这样就无法工作了。

requestInstance.picture = upPic.getBytes()你应该没事。

答案 2 :(得分:1)

仅当我将域属性picture1,picture2,picture3更改为:

时才有效
byte [] picture1
byte [] picture2
byte [] picture3

并添加了这些映射:

    static mapping = {
    picture1 column:"picture1", sqlType: "blob"
    picture2 column:"picture2", sqlType: "blob"
    picture3 column:"picture3", sqlType: "blob"
}