You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by re...@apache.org on 2021/04/08 10:40:35 UTC

[wicket] 01/01: [WICKET-6876] add an AJAX behavior to transfer client side file information to server side (when a file is selected for upload at client side).

This is an automated email from the ASF dual-hosted git repository.

reiern70 pushed a commit to branch WICKET-6878
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit c82bf07408164a73d55c89dcdf0570a2f1f148eb
Author: reiern70 <re...@gmail.com>
AuthorDate: Thu Apr 8 08:09:02 2021 +0300

    [WICKET-6876] add an AJAX behavior to transfer client side file information to server side (when a file is selected for upload at client side).
---
 .../markup/html/form/upload/FileUploadField.java   | 78 ++++++++++++++++++++++
 .../examples/ajax/builtin/FileUploadPage.html      |  5 +-
 .../examples/ajax/builtin/FileUploadPage.java      | 49 +++++++++++++-
 3 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/FileUploadField.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/FileUploadField.java
index 5a8f288..5654470 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/FileUploadField.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/upload/FileUploadField.java
@@ -18,14 +18,24 @@ package org.apache.wicket.markup.html.form.upload;
 
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 import org.apache.commons.fileupload.FileItem;
+import org.apache.wicket.Component;
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.ajax.attributes.IAjaxCallListener;
+import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.list.Loop;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.protocol.http.IMultipartWebRequest;
+import org.apache.wicket.request.IRequestParameters;
 import org.apache.wicket.request.Request;
+import org.apache.wicket.request.cycle.RequestCycle;
 import org.apache.wicket.util.convert.ConversionException;
 import org.apache.wicket.util.string.Strings;
 
@@ -47,6 +57,74 @@ public class FileUploadField extends FormComponent<List<FileUpload>>
 {
 	private static final long serialVersionUID = 1L;
 
+	/**
+	 *  {@link org.apache.wicket.ajax.form.OnChangeAjaxBehavior} that streams back to server properties
+	 *  of the selected file (at client side), even when file has not yet being uploaded.
+s	 *
+	 * @author Ernesto Reinaldo Barreiro (reiern70@gmail.com).
+	 */
+	public static abstract class OnFileSelectedBehavior extends OnChangeAjaxBehavior
+	{
+		private static final long serialVersionUID = 1L;
+
+		@Override
+		protected void onBind() {
+			super.onBind();
+			Component component = getComponent();
+			if (!(component instanceof FileUploadField))
+			{
+				throw new WicketRuntimeException("Behavior " + getClass().getName()
+						+ " can only be added to an instance of a FileUploadField");
+			}
+		}
+
+		@Override
+		protected void onUpdate(AjaxRequestTarget target)
+		{
+			Request request = RequestCycle.get().getRequest();
+			IRequestParameters parameters = request.getRequestParameters();
+			String fileName = parameters.getParameterValue("fileName").toString();
+			long fileSize = parameters.getParameterValue("fileSize").toLong(0);
+			Date lastModified = new Date(parameters.getParameterValue("lastModified").toLong(0));
+			String mimeType = parameters.getParameterValue("mimeType").toString();
+			onFileSelected(target, fileName, fileSize, lastModified, mimeType);
+		}
+
+		/**
+		 * Called when a file, at client side is selected.
+		 *
+		 * @param target The {@link org.apache.wicket.ajax.AjaxRequestTarget}
+		 * @param fileName The client file name
+		 * @param fileSize The client file size
+		 * @param lastModified The {@link java.util.Date} when file was last modified.
+		 * @param mimeType The  MIME type of file.
+		 */
+		protected abstract void onFileSelected(AjaxRequestTarget target, String fileName, long fileSize,
+											   Date lastModified, String mimeType);
+
+		@Override
+		protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+			super.updateAjaxAttributes(attributes);
+			attributes.getAjaxCallListeners().add(new IAjaxCallListener()
+			{
+				@Override
+				public CharSequence getPrecondition(Component component)
+				{
+					return "if (this.files) {  window."+component.getMarkupId()+"_file = this.files[0]; return true; } " +
+							"else return false;";
+				}
+			});
+
+			String varName = "window."+getComponent().getMarkupId()+"_file";
+			attributes.getDynamicExtraParameters().add("return {" +
+					"'fileName': " + varName + ".name, " +
+					"'fileSize': " + varName + ".size, " +
+					"'lastModified': " + varName + ".lastModified, " +
+					"'mimeType': " + varName + ".type, " +
+					"};");
+		}
+	}
+
 	private transient List<FileUpload> fileUploads;
 
 	/**
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
index 3d54b24..4296fbc 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.html
@@ -11,8 +11,11 @@ Demonstrates Wicket's ability to transparently handle multipart forms via AJAX.<
 <form wicket:id="form">
 	Text field: <input wicket:id="text" type="text"/><br/>
 	File field: <input wicket:id="file" type="file"/> (<span wicket:id="max"></span> max)<br/><br/>
+	<br/>
+	<div wicket:id="selectedFileInfo"></div>
+	<br/>
 	<div wicket:id="progress"></div>
-	<input type="submit" value="Regular Submit"/> <input wicket:id="ajaxSubmit" type="button" value="Ajax Submit"/>
+	<input wicket:id="submit" type="submit" value="Regular Submit"/> <input wicket:id="ajaxSubmit" type="button" value="Ajax Submit"/>
 </form>
 
 <div wicket:id="drop" class="drop-zone">
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
index c7f25fb..7b1692c 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/ajax/builtin/FileUploadPage.java
@@ -16,6 +16,7 @@
  */
 package org.apache.wicket.examples.ajax.builtin;
 
+import java.util.Date;
 import java.util.List;
 
 import org.apache.commons.fileupload.FileUploadException;
@@ -26,11 +27,13 @@ import org.apache.wicket.extensions.ajax.AjaxFileDropBehavior;
 import org.apache.wicket.extensions.ajax.markup.html.form.upload.UploadProgressBar;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Button;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.TextField;
 import org.apache.wicket.markup.html.form.upload.FileUpload;
 import org.apache.wicket.markup.html.form.upload.FileUploadField;
 import org.apache.wicket.markup.html.panel.FeedbackPanel;
+import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.util.lang.Bytes;
 import org.apache.wicket.validation.validator.StringValidator;
@@ -46,13 +49,16 @@ public class FileUploadPage extends BasePage
 
 	private final FileUploadField file;
 	private final TextField<String> text;
+	private final Label selectedFileInfo;
+	private final AjaxButton ajaxSubmit;
+	private final Button submit;
+	private String fileInfo;
 
 	/**
 	 * Constructor
 	 */
 	public FileUploadPage()
 	{
-
 		// create a feedback panel
 		final Component feedback = new FeedbackPanel("feedback").setOutputMarkupId(true);
 		add(feedback);
@@ -88,13 +94,51 @@ public class FileUploadPage extends BasePage
 
 		// create the file upload field
 		form.add(file = new FileUploadField("file"));
+		file.add(new FileUploadField.OnFileSelectedBehavior()
+		{
+			@Override
+			protected void onFileSelected(AjaxRequestTarget target, String fileName, long fileSize, Date lastModified, String mimeType)
+			{
+				Bytes bytes = Bytes.bytes(fileSize);
+				fileInfo = "File " + fileName + " (with size " + bytes + ") was selected at client side. "
+						+ "File was last modified at: " + lastModified
+						+ " and is of type " + mimeType +
+						". It has not been uploaded yet. ";
+				if (bytes.greaterThan(form.getMaxSize())) {
+					fileInfo += " File exceeds max allowed size.";
+					// disable buttons as file is not valid
+					submit.setEnabled(false);
+					ajaxSubmit.setEnabled(false);
+				} else {
+					fileInfo += " You can click on buttons bellow in order to upload it.";
+					// enable buttons as file is valid
+					submit.setEnabled(true);
+					ajaxSubmit.setEnabled(true);
+				}
+				target.add(selectedFileInfo, submit, ajaxSubmit);
+			}
+		});
+
+		add(selectedFileInfo = new Label("selectedFileInfo", (IModel<String>) () -> fileInfo) {
+			@Override
+			protected void onAfterRender() {
+				super.onAfterRender();
+				fileInfo = null;
+			}
+		});
+		selectedFileInfo.setOutputMarkupId(true);
+		form.add(selectedFileInfo);
 
 		form.add(new Label("max", form::getMaxSize));
 
 		form.add(new UploadProgressBar("progress", form, file));
 
+		// create a submit button
+		form.add(submit = new Button("submit"));
+		submit.setOutputMarkupId(true);
+
 		// create the ajax button used to submit the form
-		form.add(new AjaxButton("ajaxSubmit")
+		form.add(ajaxSubmit = new AjaxButton("ajaxSubmit")
 		{
 			private static final long serialVersionUID = 1L;
 
@@ -124,6 +168,7 @@ public class FileUploadPage extends BasePage
 			}
 
 		});
+		ajaxSubmit.setOutputMarkupId(true);
 		
 		WebMarkupContainer drop = new WebMarkupContainer("drop");
 		drop.add(new AjaxFileDropBehavior() {