Ant's
Ant's

Reputation: 13811

How to get bytes (byte[]) from an uploaded file in Grails

I have a upload form like this (form.gsp):

<html>
<head>
    <title>Upload Image</title>
    <meta name="layout" content="main" />
</head>
    <body>  
        <g:uploadForm action ="upload">
            Photo: <input name="photos" type="file" />
            <g:submitButton name="upload" value="Upload" />
        </g:uploadForm>
    </body>
</html>

I expect the user to upload any picture, and when he clicks on the upload button, I need some way to get the image in my controller action and passed it to the view :

def upload = { 
        byte[] photo = params.photos
            //other code goes here . . . .
    }

This throws an error :

Cannot cast object 'org.springframework.web.multipart.commons.CommonsMultipartFile@1b40272' with class 'org.springframework.web.multipart.commons.CommonsMultipartFile' to class 'byte'

Note that I don't want these photos to be saved on my DB. Actually once the upload action is done, I will process with that image and show the output in upload view itself. So it will be good if I have a solution for it.

Thanks in advance.

Upvotes: 7

Views: 10484

Answers (3)

Rob Hruska
Rob Hruska

Reputation: 120286

If you want to upload the file, not store it, and display it in an <img> on another view in the next request, you could temporarily store it in the session:

grails-app/controllers/UploadController.groovy:

def upload = {
    def file = request.getFile('file')

    session.file = [
        bytes: file.inputStream.bytes,
        contentType: file.contentType
    ]

    redirect action: 'elsewhere'
}

def elsewhere = { }

def image = {
    if (!session.file) {
        response.sendError(404)
        return
    }

    def file = session.file
    session.removeAttribute 'file'

    response.setHeader('Cache-Control', 'no-cache')
    response.contentType = file.contentType
    response.outputStream << file.bytes
    response.outputStream.flush()

}

grails-app/views/upload/form.gsp:

<g:uploadForm action="upload">
  <input type="file" name="file"/>
  <g:submitButton name="Upload"/>
</g:uploadForm>

grails-app/views/upload/elsewhere.gsp:

<img src="${createLink(controller: 'upload', action: 'image')}"/>

The file will be available for a single request (since we remove it when it's displayed). You might need to implement some additional session cleanup for error cases.

You could easily adapt this to hold onto multiple files (if you're trying to stage a bunch of photo uploads), but keep in mind that each file's taking up memory.

An alternative to using the session would be to transfer the files to a temporary location on disk using MultipartFile#transferTo(File) and display them from there.

Upvotes: 9

fixitagain
fixitagain

Reputation: 6733

byte[] photo=request.getFile("photos").bytes

and if you want to return as an image do:

response.contentType="image/png" //or whatever the format is...
response.outputStream << photo

Upvotes: 5

Jan Wikholm
Jan Wikholm

Reputation: 1575

def reqFile = request.getFile("photos")
InputStream file = reqFile.inputStream
byte[] bytes = file.bytes

Edit: changed the getBytes to bytes as suggested and as is a better groovy way :)

Upvotes: 11

Related Questions