Open kerfanch opened 10 years ago
+1
kerfanch have you found workaround? Have the same problem...
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&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"> </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>
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
I created a new fresh grails app (2.3.1) to test your plugin.
here's a part of my BuildConfig.groovy :
And here's my view page used for the test :
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.