Grails загрузить изображение - PullRequest
3 голосов
/ 01 декабря 2011

Я пытаюсь загрузить изображение и сохранить его в базе данных.Если я делаю следующее, я получаю эту ошибку:

Не удалось преобразовать значение свойства типа

org.springframework.web.multipart.commons.CommonsMultipartFile в требуемый тип java.lang.Байт [] для свойства picture1;вложенным исключением является java.lang.IllegalArgumentException: невозможно преобразовать значение типа [org.springframework.web.multipart.commons.CommonsMultipartFile] в требуемый тип [java.lang.Byte] для свойства picture1 [0]: PropertyEditor [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 'в класс'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 ]

6 голосов
/ 01 декабря 2011

Обновление после редактирования вопроса

Ошибка, вероятно, вызвана этим:

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.properties или bindData().
3 голосов
/ 01 декабря 2011

Я полагаю, что вы неправильно набрали текст.

Что произойдет, если вы просто сделаете:

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() и с вами все будет в порядке.

1 голос
/ 02 декабря 2011

Это сработало только тогда, когда я изменил свойства своего домена 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"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...