Grails download file

15,448

Solution 1

I have done something similar to following:

Assuming your download page has the relevant Submissions instance...

<g:link action="downloadFile" id="${aSubmission.id}">
    <img>...etc...</img>
</g:link>

Then in controller (is your "location" the path to the file?):

def downloadFile = {
    def sub = Submissions.get(params.id)
    def file = new File("${sub.location}/${sub.fileName")
    if (file.exists())
    {
        response.setContentType("application/octet-stream") // or or image/JPEG or text/xml or whatever type the file is
        response.setHeader("Content-disposition", "attachment;filename=\"${file.name}\"")
        response.outputStream << file.bytes
    }
    else render "Error!" // appropriate error handling
}

Solution 2

Well, it's always better to keep your download logic wrapped inside a try / catch and also set webrequest as false. http://lalitagarw.blogspot.in/2014/03/grails-forcing-file-download.html

def downloadFile() {
    InputStream contentStream
    try {
        def file = new File("<path>")  
        response.setHeader "Content-disposition", "attachment; filename=filename-with-extension"
        response.setHeader("Content-Length", "file-size")
        response.setContentType("file-mime-type")
        contentStream = file.newInputStream()
        response.outputStream << contentStream
        webRequest.renderView = false
    } finally {
        IOUtils.closeQuietly(contentStream)
    }
}

Solution 3

I used the FCKEditor WYSIWYG editor http://www.grails.org/plugin/fckeditor this is also an easy to use file downloader.

Solution 4

you simply need to render the bytes on the response. We do something like

def streamFile = {
    // load the attachment by id passed on params
    ....
    response.contentType = attachment.contentType.toLowerCase()
    response.contentLength = attachment.data.length()
    // our 'data' field is a Blob, the important thing here is to get the bytes according to
    // how you get the actual downlaod
    response.outputStream.write(attachment.data.getBytes(1L, attachment.data?.length() as int))
}

in our controller, and just create a link to that controller method on the gsp. Depending on how you se the content type, the browser will do stuff for you. If you have an image type for example, it will show the image. If you have a word document, the browser should open the appropriate program for the user's system.

Share:
15,448
Michael
Author by

Michael

Updated on June 05, 2022

Comments

  • Michael
    Michael almost 2 years

    I'v used this method to copy a file to a folder in my project(first method), and I have edited it so the location is stored on my 'Location' in class Submissions (see below).

    Now I want to be able to, after clicking on an image in my view, download that file. How can I do that ?

    class Submissions {
    
        Date dateSub
        String Location
        String fileName
    
    }
    
  • Michael
    Michael almost 13 years
    hm you are talking about bytes here .. The files are not storared in the database, only its location. Are you taking it into account right?
  • hvgotcodes
    hvgotcodes almost 13 years
    @michael if you store the path in the db, you need to get a File object, and then get the bytes.
  • praveen2609
    praveen2609 over 10 years
    It worked, give error for file.exists as there is no such method it should be file.exists()