Skip to content

Instantly share code, notes, and snippets.

@xfyre
Last active February 24, 2019 16:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xfyre/83f82f6e5145ee041217 to your computer and use it in GitHub Desktop.
Save xfyre/83f82f6e5145ee041217 to your computer and use it in GitHub Desktop.
Tapestry 5.4 AJAX upload component
package my.app.components;
import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.corelib.base.AbstractField;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONArray;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.FormSupport;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.InitializationPriority;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.upload.services.MultipartDecoder;
import org.apache.tapestry5.upload.services.UploadedFile;
@Events(AjaxUpload.EVENT_FILE_UPLOADED)
@SupportsInformalParameters
public class AjaxUpload extends AbstractField {
public static final String MULTIPART_ENCTYPE = "multipart/form-data";
public static final String EVENT_FILE_UPLOADED = "fileUploaded";
@Parameter(defaultPrefix=BindingConstants.PROP,required=true,principal=true,autoconnect=true)
private UploadedFile value;
@Parameter(defaultPrefix=BindingConstants.VALIDATE)
private FieldValidator<Object> validate;
@Parameter(defaultPrefix=BindingConstants.LITERAL,required=true,value="false")
private Boolean multiple;
@Inject
private ComponentResources resources;
@Inject
private Messages messages;
@Inject
private MultipartDecoder decoder;
@Environmental
private JavaScriptSupport javaScriptSupport;
public AjaxUpload () {
}
Binding defaultValidate() {
return defaultProvider.defaultValidatorBinding ( "value", resources );
}
@SuppressWarnings("deprecation")
AjaxUpload injectDecorator ( ValidationDecorator decorator ) {
setDecorator ( decorator );
return this;
}
AjaxUpload injectRequest ( Request request ) {
this.request = request;
return this;
}
AjaxUpload injectFormSupport ( FormSupport formSupport ) {
// We have our copy ...
this.formSupport = formSupport;
// As does AbstractField
setFormSupport ( formSupport );
return this;
}
AjaxUpload injectFieldValidator ( FieldValidator<Object> validator ) {
this.validate = validator;
return this;
}
void beginRender ( MarkupWriter writer ) {
formSupport.setEncodingType ( MULTIPART_ENCTYPE );
writer.element ( "div", "class", "form-control-static" );
writer.element ( "span", "class", "btn btn-primary fileinput-button" );
writer.element ( "i", "class", "glyphicon glyphicon-upload" ); writer.end ();
writer.writeRaw ( "&#160;" );
writer.element ( "span" ).raw ( messages.get ( "button.upload" ) ); writer.end ();
writer.element ( "input", "type", "file", "id", getClientId (), "name", getControlName () );
validate.render ( writer );
resources.renderInformalParameters ( writer );
decorateInsideField();
writer.end (); // input field
writer.end (); // button span
writer.end (); // container div
}
@Import(stylesheet={"context:blueimp-file-upload-9.5.7/css/jquery.fileupload.css"})
void afterRender ( MarkupWriter writer ) {
JSONObject spec = new JSONObject (
"url", resources.createEventLink ( "upload", getControlName () ).toAbsoluteURI (),
"inputId", getClientId ()
);
javaScriptSupport.require ( "dcnet/ajaxupload" ).priority ( InitializationPriority.LATE ).with ( spec );
}
Object onUpload ( String controlName ) {
value = decoder.getFileUpload ( controlName );
final Holder<JSONObject> holder = new Holder<JSONObject> ();
ComponentEventCallback<JSONObject> callback = new ComponentEventCallback<JSONObject> () {
@Override
public boolean handleResult ( JSONObject result ) {
if ( result != null ) {
holder.put ( result );
return true;
}
return false;
}
};
resources.triggerEvent ( EVENT_FILE_UPLOADED, new Object[] { value }, callback );
JSONArray files = new JSONArray ();
if ( holder.hasValue () )
files.put ( holder.get () );
else
files.put ( new JSONObject (
"name", value.getFileName (),
"size", value.getSize (),
"thumbnailUrl", resources.createEventLink ( "preview", value.getFileName () ).toAbsoluteURI (),
"deleteUrl", resources.createEventLink ( "delete", value.getFileName () ).toAbsoluteURI (),
"deleteType", "GET"
) );
return new JSONObject ( "files", files );
}
@Override
protected void processSubmission ( String controlName ) {
}
}
define(["jquery", "blueimp/jquery.fileupload"], function($) {
return function(spec) {
var $input = $('#' + spec.inputId);
var $button = $input.closest('.fileinput-button');
var filenameId = spec.inputId + '_filename';
$input.fileupload({
dataType: 'json',
sequentialUploads: true,
autoUpload: true,
url: spec.url,
send: function(e, data) {
$button.attr('disabled', 'disabled');
$('#' + filenameId).remove();
return true;
},
done: function(e, data) {
$button.removeAttr('disabled');
var filename = data.files[0].name;
var size = Math.round(data.files[0].size / 1024);
$button.after($('<span id="' + filenameId + '" style="margin-left: 16px;">' + filename + ' (' + size + ' KB)</span>'));
}
});
};
});
@xfyre
Copy link
Author

xfyre commented Jun 15, 2014

This is a simple AJAX upload component based on https://github.com/blueimp/jQuery-File-Upload.
To set it up:

  • unpack jQuery-File-Upload distribution into META-INF/modules/blueimp
  • add required dependencies (load-image, canvas-to-blob and tmpl) into the same directory
  • NOTE: you need to use non-minified versions
  • fix dependency references in jQuery-File-Upload sources (for example, 'tmpl' should become './tmpl', so Tapestry will request modules from the same directory)
  • contribute service override for MultipartDecoder (see http://tawus.wordpress.com/2011/06/25/ajax-upload-for-tapestry/ for instructions how to do that)

@Brounchy
Copy link

Thx guy, it works perfectly !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment