sarbogast / grails-bootstrap-file-upload

Grails Plugin to integrate Sebastian Tschan's Jquery File Upload
http://grails.org/plugin/bootstrap-file-upload
Apache License 2.0
33 stars 25 forks source link

File not added to table when selecting image in the file explorer #18

Open kerfanch opened 10 years ago

kerfanch commented 10 years ago

I created a new fresh grails app (2.3.1) to test your plugin.

here's a part of my BuildConfig.groovy :

plugins {
    // plugins for the build system only
    build ":tomcat:7.0.42"

    // plugins for the compile step
    compile ":scaffolding:2.0.1"
    compile ':cache:1.1.1'

    // plugins needed at runtime but not for compilation
    runtime ":hibernate:3.6.10.2" // or ":hibernate4:4.1.11.2"
    runtime ":database-migration:1.3.5"
    runtime ":jquery:1.10.2"
    runtime ":resources:1.2.1"
    // Uncomment these (or add new ones) to enable additional resources capabilities
    //runtime ":zipped-resources:1.0.1"
    //runtime ":cached-resources:1.1"
    //runtime ":yui-minify-resources:0.1.5"

    compile ":jquery-ui:1.10.3"
    compile ":twitter-bootstrap:3.0.2"
    compile ":bootstrap-file-upload:2.1.2"
}

And here's my view page used for the test :

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>jQuery File Upload Demo</title>
  <meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support, progress bar and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.">
  <meta name="viewport" content="width=device-width">

  <r:require modules="bootstrap-file-upload, bootstrap-image-gallery"/>

  <!-- Shim to make HTML5 elements usable in older Internet Explorer versions -->
  <!--[if lt IE 9]><script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script><![endif]-->

  <r:layoutResources/>
</head>
<body style="padding-top: 60px;">
<div class="container">
  <div class="page-header">
    <h1>jQuery File Upload Demo</h1>
  </div>
  <bsfu:fileUpload controller="image" action="upload"/>
</div>
<bsfu:imageGallery/>
<r:layoutResources/>
</body>
</html>

I click on the "Add Files", then I select a png file from the file explorer. The selected file is not appended to the table list. Nothing seems to be happened....

Your plugin is really good and I would like to integrate in my app.

Please help me.

ctacon commented 10 years ago

+1

ctacon commented 10 years ago

kerfanch have you found workaround? Have the same problem...

kerfanch commented 10 years ago

Hi ctacon,

Here's my workaround :

The sample controller (JQueryFileUploadController.groovy)

package test

import org.springframework.http.HttpStatus
import grails.converters.JSON
import org.springframework.web.multipart.MultipartHttpServletRequest
import org.springframework.web.multipart.MultipartFile
import org.imgscalr.Scalr
import java.awt.image.BufferedImage
import javax.imageio.ImageIO

class JqueryFileUploadController {
def index() { }

def upload() {
    println "Entering upload...."
    switch(request.method){
        case "GET":
            println "GET Request"
            def results = []
            Image.findAll().each { Image picture ->
                results << [
                        name: picture.originalFilename,
                        size: picture.fileSize,
                        url: createLink(controller:'jqueryFileUpload', action:'picture', id: picture.id),
                        thumbnailUrl: createLink(controller:'jqueryFileUpload', action:'thumbnail', id: picture.id),
                        deleteUrl: createLink(controller:'jqueryFileUpload', action:'delete', id: picture.id),
                        deleteType: "DELETE"
                ]
            }
            println "results : "+results
            render(contentType: 'text/json') {[ 'files': results ]}
//                render results as JSON
    break;
    case "POST":
            println "POST Request"
            def results = []
            if (request instanceof MultipartHttpServletRequest){
                for(filename in request.getFileNames()){
                    MultipartFile file = request.getFile(filename)
                    println "file name : "+file.originalFilename

                    String newFilenameBase = UUID.randomUUID().toString()
                    String originalFileExtension = file.originalFilename.substring(file.originalFilename.lastIndexOf("."))
                    String newFilename = newFilenameBase + originalFileExtension
                    String storageDirectory = grailsApplication.config.file.upload.directory?:'/home/kerfanch/tmp'

                    File newFile = new File("$storageDirectory/$newFilename")
                    file.transferTo(newFile)
                    println "file transferred : "+"$storageDirectory/$newFilename"

                    BufferedImage thumbnail = Scalr.resize(ImageIO.read(newFile), 290);
                    String thumbnailFilename = newFilenameBase + '-thumbnail.png'
                    File thumbnailFile = new File("$storageDirectory/$thumbnailFilename")
                    ImageIO.write(thumbnail, 'png', thumbnailFile)

                    Image picture = new Image(
                            originalFilename: file.originalFilename,
                            thumbnailFilename: thumbnailFilename,
                            newFilename: newFilename,
                            fileSize: file.size
                    ).save()

                    results << [
                            name: picture.originalFilename,
                            size: picture.fileSize,
                            url: createLink(controller:'jqueryFileUpload', action:'picture', id: picture.id),
                            thumbnailUrl: createLink(controller:'jqueryFileUpload', action:'thumbnail', id: picture.id),
                            deleteUrl: createLink(controller:'jqueryFileUpload', action:'delete', id: picture.id),
                            deleteType: "DELETE"
                    ]
                }
            }

            println "results : "+results
            render(contentType: 'text/json') {[ 'files': results ]}
//                render results as JSON
    break;
    default: render status: HttpStatus.METHOD_NOT_ALLOWED.value()
}
}

def picture(){
    println "Entering picture()..."
    def pic = Image.get(params.id)
    File picFile = new File("${grailsApplication.config.file.upload.directory?:'/home/kerfanch/tmp'}/${pic.newFilename}")
    response.contentType = 'image/jpeg'
    response.outputStream << new FileInputStream(picFile)
    response.outputStream.flush()
}

def thumbnail(){
    println "Entering thumbnail()..."
    def pic = Image.get(params.id)
    File picFile = new File("${grailsApplication.config.file.upload.directory?:'/home/kerfanch/tmp'}/${pic.thumbnailFilename}")
    response.contentType = 'image/png'
    response.outputStream << new FileInputStream(picFile)
    response.outputStream.flush()
}

def delete(){
    println "Entering delete()..."
    def pic = Image.get(params.id)
    File picFile = new File("${grailsApplication.config.file.upload.directory?:'/home/kerfanch/tmp'}/${pic.newFilename}")
    picFile.delete()
    File thumbnailFile = new File("${grailsApplication.config.file.upload.directory?:'/home/kerfanch/tmp'}/${pic.thumbnailFilename}")
    thumbnailFile.delete()
    pic.delete()

    def result = [success: true]
    render result as JSON
}

}

The sample view (jqueryFileUpload/index.gsp)

<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- Force latest IE rendering engine or ChromeFrame if installed -->
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<![endif]-->
<meta charset="utf-8">
<title>jQuery File Upload Demo</title>
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<r:require modules="jquery, jquery-ui, bootstrap"/>
<!-- Generic page styles -->
<link rel="stylesheet" href="${resource(dir: 'css', file: 'style.css')}">
<!-- blueimp Gallery styles -->
<link rel="stylesheet" href="http://blueimp.github.io/Gallery/css/blueimp-gallery.min.css">
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="${resource(dir: 'css', file: 'jquery.fileupload.css')}">
<link rel="stylesheet" href="${resource(dir: 'css', file: 'jquery.fileupload-ui.css')}">
<!-- CSS adjustments for browsers with JavaScript disabled -->
<noscript>
    <link rel="stylesheet" href="${resource(dir: 'css', file: 'jquery.fileupload-noscript.css')}">
</noscript>
<noscript>
    <link rel="stylesheet" href="${resource(dir: 'css', file: 'jquery.fileupload-ui-noscript.css')}">
</noscript>
<r:layoutResources />
</head>
<body>
<div class="container">
    <h1>jQuery File Upload Demo</h1>
    <!-- The file upload form used as target for the file upload widget -->
    <form id="fileupload" action="upload" method="POST" enctype="multipart/form-data">
        <!-- Redirect browsers with JavaScript disabled to the origin page -->
        <noscript><input type="hidden" name="redirect" value="http://blueimp.github.io/jQuery-File-Upload/"></noscript>
        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
        <div class="row fileupload-buttonbar">
            <div class="col-lg-7">
                <!-- The fileinput-button span is used to style the file input field as button -->
                <span class="btn btn-success fileinput-button">
                    <i class="glyphicon glyphicon-plus"></i>
                    <span>Add files...</span>
                    <input type="file" name="files[]" multiple>
                </span>
                <button type="submit" class="btn btn-primary start">
                    <i class="glyphicon glyphicon-upload"></i>
                    <span>Start upload</span>
                </button>
                <button type="reset" class="btn btn-warning cancel">
                    <i class="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel upload</span>
                </button>
                <button type="button" class="btn btn-danger delete">
                    <i class="glyphicon glyphicon-trash"></i>
                    <span>Delete</span>
                </button>
                <input type="checkbox" class="toggle">
                <!-- The global file processing state -->
                <span class="fileupload-process"></span>
            </div>
            <!-- The global progress state -->
            <div class="col-lg-5 fileupload-progress fade">
                <!-- The global progress bar -->
                <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
                    <div class="progress-bar progress-bar-success" style="width:0%;"></div>
                </div>
                <!-- The extended global progress state -->
                <div class="progress-extended">&nbsp;</div>
            </div>
        </div>
        <!-- The table listing the files available for upload/download -->
        <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
    </form>
</div>
<!-- The blueimp Gallery widget -->
<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even">
    <div class="slides"></div>
    <h3 class="title"></h3>
    <a class="prev">‹</a>
    <a class="next">›</a>
    <a class="close">×</a>
    <a class="play-pause"></a>
    <ol class="indicator"></ol>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
    <tr class="template-upload fade">
        <td>
            <span class="preview"></span>
        </td>
        <td>
            <p class="name">{%=file.name%}</p>
            <strong class="error text-danger"></strong>
        </td>
        <td>
            <p class="size">Processing...</p>
            <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
        </td>
        <td>
            {% if (!i && !o.options.autoUpload) { %}
                <button class="btn btn-primary start" disabled>
                    <i class="glyphicon glyphicon-upload"></i>
                    <span>Start</span>
                </button>
            {% } %}
            {% if (!i) { %}
                <button class="btn btn-warning cancel">
                    <i class="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel</span>
                </button>
            {% } %}
        </td>
    </tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
    <tr class="template-download fade">
        <td>
            <span class="preview">
                {% if (file.thumbnailUrl) { %}
                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
                {% } %}
            </span>
        </td>
        <td>
            <p class="name">
                {% if (file.url) { %}
                    <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
                {% } else { %}
                    <span>{%=file.name%}</span>
                {% } %}
            </p>
            {% if (file.error) { %}
                <div><span class="label label-danger">Error</span> {%=file.error%}</div>
            {% } %}
        </td>
        <td>
            <span class="size">{%=o.formatFileSize(file.size)%}</span>
        </td>
        <td>
            {% if (file.deleteUrl) { %}
                <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
                    <i class="glyphicon glyphicon-trash"></i>
                    <span>Delete</span>
                </button>
                <input type="checkbox" name="delete" value="1" class="toggle">
            {% } else { %}
                <button class="btn btn-warning cancel">
                    <i class="glyphicon glyphicon-ban-circle"></i>
                    <span>Cancel</span>
                </button>
            {% } %}
        </td>
    </tr>
{% } %}
</script>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="${resource(dir: 'js/vendor', file: 'jquery.ui.widget.js')}"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="http://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="http://blueimp.github.io/JavaScript-Load-Image/js/load-image.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="http://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<!-- blueimp Gallery script -->
<script src="http://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="${resource(dir: 'js', file: 'jquery.iframe-transport.js')}"></script>
<!-- The basic File Upload plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload.js')}"></script>
<!-- The File Upload processing plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-process.js')}"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-image.js')}"></script>
<!-- The File Upload audio preview plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-audio.js')}"></script>
<!-- The File Upload video preview plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-video.js')}"></script>
<!-- The File Upload validation plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-validate.js')}"></script>
<!-- The File Upload user interface plugin -->
<script src="${resource(dir: 'js', file: 'jquery.fileupload-ui.js')}"></script>
<!-- The main application script -->
<script src="${resource(dir: 'js', file: 'main.js')}"></script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="${resource(dir: 'js/cors', file: 'jquery.xdr-transport.js')}"></script>
<![endif]-->
<r:layoutResources />
</body> 
</html>
cebatista commented 10 years ago

Hi kerfanch,

I used your example but not worked very well, would you please help-me.

When I select 2 images from my folder, the plugin don't show this images in the page like example from this link: http://blueimp.github.io/jQuery-File-Upload/ and when start the upload, only 1 image was uploaded to the temp folder.

I created a new grails app (2.3.5) to test.

here's a part of my BuildConfig.groovy :

    plugins {
        build ":tomcat:7.0.50"
        compile ":scaffolding:2.0.1"
        compile ':cache:1.1.1'

        runtime ":hibernate:3.6.10.7" // or ":hibernate4:4.1.11.6"
        runtime ":database-migration:1.3.8"
        runtime ":jquery:1.10.2.2"
        runtime ":resources:1.2.1"
        compile ":twitter-bootstrap:3.1.1"
        compile ":bootstrap-file-upload:2.1.2"
        compile ":jquery-ui:1.10.3"
    }

here's the the sample (jqueryFileUpload/index.gsp):

<!DOCTYPE html>
<html>
    <head>
        <meta name="layout" content="main2"/>
        <r:require modules="bootstrap-file-upload"/>    
    </head>
    <body>
        <form id="fileupload" action="upload" method="POST" enctype="multipart/form-data">
            <bsfu:fileUpload action="upload" controller="image"/>
            <bsfu:imageGallery/>
        </form>
    </body>

</html> 

the controller is the same of example:

jqueryFileUploadController.groovy

Here is an example implementation of the controller:

import org.springframework.http.HttpStatus
import grails.converters.JSON
import org.springframework.web.multipart.MultipartHttpServletRequest
import org.springframework.web.multipart.MultipartFile
import java.awt.image.BufferedImage
import org.imgscalr.Scalr
import javax.imageio.ImageIO

class ImageController {
    def upload() {
        switch(request.method){
            case "GET":
                def results = []
                Image.findAll().each { Image picture ->
                    results << [
                            name: picture.originalFilename,
                            size: picture.fileSize,
                            url: createLink(controller:'image', action:'picture', id: picture.id),
                            thumbnail_url: createLink(controller:'image', action:'thumbnail', id: picture.id),
                            delete_url: createLink(controller:'image', action:'delete', id: picture.id),
                            delete_type: "DELETE"
                    ]
                }
                render results as JSON
                break;
            case "POST":
                def results = []
                if (request instanceof MultipartHttpServletRequest){
                    for(filename in request.getFileNames()){
                        MultipartFile file = request.getFile(filename)

                        String newFilenameBase = UUID.randomUUID().toString()
                        String originalFileExtension = file.originalFilename.substring(file.originalFilename.lastIndexOf("."))
                        String newFilename = newFilenameBase + originalFileExtension
                        String storageDirectory = grailsApplication.config.file.upload.directory?:'/tmp'

                        File newFile = new File("$storageDirectory/$newFilename")
                        file.transferTo(newFile)

                        BufferedImage thumbnail = Scalr.resize(ImageIO.read(newFile), 290);
                        String thumbnailFilename = newFilenameBase + '-thumbnail.png'
                        File thumbnailFile = new File("$storageDirectory/$thumbnailFilename")
                        ImageIO.write(thumbnail, 'png', thumbnailFile)

                        Image picture = new Image(
                                originalFilename: file.originalFilename,
                                thumbnailFilename: thumbnailFilename,
                                newFilename: newFilename,
                                fileSize: file.size
                        ).save()

                        results << [
                                name: picture.originalFilename,
                                size: picture.fileSize,
                                url: createLink(controller:'image', action:'picture', id: picture.id),
                                thumbnail_url: createLink(controller:'image', action:'thumbnail', id: picture.id),
                                delete_url: createLink(controller:'image', action:'delete', id: picture.id),
                                delete_type: "DELETE"
                        ]
                    }
                }

                render results as JSON
                break;
            default: render status: HttpStatus.METHOD_NOT_ALLOWED.value()
        }
    }

    def picture(){
        def pic = Image.get(params.id)
        File picFile = new File("${grailsApplication.config.file.upload.directory?:'/tmp'}/${pic.newFilename}")
        response.contentType = 'image/jpeg'
        response.outputStream << new FileInputStream(picFile)
        response.outputStream.flush()
    }

    def thumbnail(){
        def pic = Image.get(params.id)
        File picFile = new File("${grailsApplication.config.file.upload.directory?:'/tmp'}/${pic.thumbnailFilename}")
        response.contentType = 'image/png'
        response.outputStream << new FileInputStream(picFile)
        response.outputStream.flush()
    }

    def delete(){
        def pic = Image.get(params.id)
        File picFile = new File("${grailsApplication.config.file.upload.directory?:'/tmp'}/${pic.newFilename}")
        picFile.delete()
        File thumbnailFile = new File("${grailsApplication.config.file.upload.directory?:'/tmp'}/${pic.thumbnailFilename}")
        thumbnailFile.delete()
        pic.delete()

        def result = [success: true]
        render result as JSON
    }
}

I'm sorry if I could not explain in the best way

Tks