summaryrefslogtreecommitdiffstats
path: root/src/com/itmill/toolkit/ui/Upload.java
diff options
context:
space:
mode:
authorMatti Tahvonen <matti.tahvonen@itmill.com>2007-09-27 08:43:27 +0000
committerMatti Tahvonen <matti.tahvonen@itmill.com>2007-09-27 08:43:27 +0000
commit749b99fd463276848ecbbfbbe68c850f9e313beb (patch)
treeca15633fc899b3f286f79aae367e2ff9a9377cb2 /src/com/itmill/toolkit/ui/Upload.java
parent71515370dd600b8ead68e7d76edc809c3f5f0fc2 (diff)
downloadvaadin-framework-749b99fd463276848ecbbfbbe68c850f9e313beb.tar.gz
vaadin-framework-749b99fd463276848ecbbfbbe68c850f9e313beb.zip
Streaming upload and client side implementation for upload + progressindicator
svn changeset:2381/svn branch:trunk
Diffstat (limited to 'src/com/itmill/toolkit/ui/Upload.java')
-rw-r--r--src/com/itmill/toolkit/ui/Upload.java263
1 files changed, 239 insertions, 24 deletions
diff --git a/src/com/itmill/toolkit/ui/Upload.java b/src/com/itmill/toolkit/ui/Upload.java
index 68276eab7a..ffa23f3e2b 100644
--- a/src/com/itmill/toolkit/ui/Upload.java
+++ b/src/com/itmill/toolkit/ui/Upload.java
@@ -71,6 +71,18 @@ public class Upload extends AbstractComponent implements Component.Focusable {
private long focusableId = -1;
+ private boolean isUploading;
+
+ private long contentLength = -1;
+
+ private int totalBytes;
+
+ /**
+ * ProgressListener to which information about progress is sent during
+ * upload
+ */
+ private ProgressListener progressListener;
+
/* TODO: Add a default constructor, receive to temp file. */
/**
@@ -95,25 +107,16 @@ public class Upload extends AbstractComponent implements Component.Focusable {
return "upload";
}
- /**
- * Invoked when the value of a variable has changed.
- *
- * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object,
- * java.util.Map)
- */
- public void changeVariables(Object source, Map variables) {
-
- // Checks the variable name
- if (!variables.containsKey("stream"))
- return;
-
- // Gets the upload stream
- UploadStream upload = (UploadStream) variables.get("stream");
+ public void receiveUpload(UploadStream upload) {
+ if (!isUploading)
+ throw new IllegalStateException("uploading not started");
// Gets file properties
String filename = upload.getContentName();
String type = upload.getContentType();
+ fireStarted(filename, type);
+
// Gets the output target stream
OutputStream out = receiver.receiveUpload(filename, type);
if (out == null)
@@ -121,33 +124,54 @@ public class Upload extends AbstractComponent implements Component.Focusable {
"Error getting outputstream from upload receiver");
InputStream in = upload.getStream();
+
if (null == in) {
// No file, for instance non-existent filename in html upload
fireUploadInterrupted(filename, type, 0);
+ endUpload();
return;
}
+
byte buffer[] = new byte[BUFFER_SIZE];
int bytesRead = 0;
- long totalBytes = 0;
+ totalBytes = 0;
try {
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
totalBytes += bytesRead;
+ if (progressListener != null && contentLength > 0) {
+ // update progress if listener set and contentLength
+ // received
+ progressListener.updateProgress(totalBytes, contentLength);
+ }
}
- // Download successfull
+ // upload successful
out.close();
fireUploadSuccess(filename, type, totalBytes);
+ endUpload();
requestRepaint();
} catch (IOException e) {
// Download interrupted
fireUploadInterrupted(filename, type, totalBytes);
+ endUpload();
}
}
/**
+ * Invoked when the value of a variable has changed.
+ *
+ * @see com.itmill.toolkit.ui.AbstractComponent#changeVariables(java.lang.Object,
+ * java.util.Map)
+ */
+ public void changeVariables(Object source, Map variables) {
+ // NOP
+
+ }
+
+ /**
* Paints the content of this component.
*
* @param target
@@ -164,6 +188,10 @@ public class Upload extends AbstractComponent implements Component.Focusable {
if (this.tabIndex >= 0)
target.addAttribute("tabindex", this.tabIndex);
+ target.addAttribute("state", isUploading);
+
+ target.addVariable(this, "fake", true);
+
target.addUploadStreamVariable(this, "stream");
}
@@ -198,12 +226,16 @@ public class Upload extends AbstractComponent implements Component.Focusable {
private static final Method UPLOAD_SUCCEEDED_METHOD;
+ private static final Method UPLOAD_STARTED_METHOD;
+
static {
try {
UPLOAD_FINISHED_METHOD = FinishedListener.class.getDeclaredMethod(
"uploadFinished", new Class[] { FinishedEvent.class });
UPLOAD_FAILED_METHOD = FailedListener.class.getDeclaredMethod(
"uploadFailed", new Class[] { FailedEvent.class });
+ UPLOAD_STARTED_METHOD = StartedListener.class.getDeclaredMethod(
+ "uploadStarted", new Class[] { StartedEvent.class });
UPLOAD_SUCCEEDED_METHOD = SucceededListener.class
.getDeclaredMethod("uploadSucceeded",
new Class[] { SucceededEvent.class });
@@ -282,21 +314,21 @@ public class Upload extends AbstractComponent implements Component.Focusable {
}
/**
- * Gets the length of the file.
+ * Gets the MIME Type of the file.
*
- * @return the length.
+ * @return the MIME type.
*/
- public long getLength() {
- return length;
+ public String getMIMEType() {
+ return type;
}
/**
- * Gets the MIME Type of the file.
+ * Gets the length of the file.
*
- * @return the MIME type.
+ * @return the length.
*/
- public String getMIMEType() {
- return type;
+ public long getLength() {
+ return length;
}
}
@@ -361,6 +393,85 @@ public class Upload extends AbstractComponent implements Component.Focusable {
}
/**
+ * Upload.Started event is sent when the upload is started to received.
+ *
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+ public class StartedEvent extends Component.Event {
+
+ /**
+ * Serial generated by eclipse.
+ */
+ private static final long serialVersionUID = -3984393770487403525L;
+ private String filename;
+ private String type;
+
+ /**
+ *
+ * @param source
+ * @param filename
+ * @param MIMEType
+ * @param length
+ */
+ public StartedEvent(Upload source, String filename, String MIMEType) {
+ super(source);
+ this.filename = filename;
+ this.type = MIMEType;
+ }
+
+ /**
+ * Uploads where the event occurred.
+ *
+ * @return the Source of the event.
+ */
+ public Upload getUpload() {
+ return (Upload) getSource();
+ }
+
+ /**
+ * Gets the file name.
+ *
+ * @return the filename.
+ */
+ public String getFilename() {
+ return filename;
+ }
+
+ /**
+ * Gets the MIME Type of the file.
+ *
+ * @return the MIME type.
+ */
+ public String getMIMEType() {
+ return type;
+ }
+
+
+ }
+
+ /**
+ * Receives the events when the upload starts.
+ *
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+ public interface StartedListener {
+
+ /**
+ * Upload has started.
+ *
+ * @param event
+ * the Upload started event.
+ */
+ public void uploadStarted(StartedEvent event);
+ }
+
+ /**
* Receives the events when the uploads are ready.
*
* @author IT Mill Ltd.
@@ -418,6 +529,26 @@ public class Upload extends AbstractComponent implements Component.Focusable {
}
/**
+ * Adds the upload started event listener.
+ *
+ * @param listener
+ * the Listener to be added.
+ */
+ public void addListener(StartedListener listener) {
+ addListener(StartedEvent.class, listener, UPLOAD_STARTED_METHOD);
+ }
+
+ /**
+ * Removes the upload started event listener.
+ *
+ * @param listener
+ * the Listener to be removed.
+ */
+ public void removeListener(StartedListener listener) {
+ removeListener(FinishedEvent.class, listener, UPLOAD_STARTED_METHOD);
+ }
+
+ /**
* Adds the upload received event listener.
*
* @param listener
@@ -484,6 +615,17 @@ public class Upload extends AbstractComponent implements Component.Focusable {
* @param MIMEType
* @param length
*/
+ protected void fireStarted(String filename, String MIMEType) {
+ fireEvent(new Upload.StartedEvent(this, filename, MIMEType));
+ }
+
+ /**
+ * Emit upload received event.
+ *
+ * @param filename
+ * @param MIMEType
+ * @param length
+ */
protected void fireUploadReceived(String filename, String MIMEType,
long length) {
fireEvent(new Upload.FinishedEvent(this, filename, MIMEType, length));
@@ -572,4 +714,77 @@ public class Upload extends AbstractComponent implements Component.Focusable {
return this.focusableId;
}
+ /**
+ * Sets the size of the file currently being uploaded.
+ *
+ * @param contentLength
+ */
+ public void setUploadSize(long contentLength) {
+ this.contentLength = contentLength;
+ }
+
+ /**
+ * Go into upload state. This is to prevent double uploading on same
+ * component.
+ */
+ public void startUpload() {
+ if (isUploading)
+ throw new IllegalStateException("uploading already started");
+ isUploading = true;
+ }
+
+ /**
+ * Go into state where new uploading can begin.
+ */
+ public void endUpload() {
+ isUploading = false;
+ contentLength = -1;
+ }
+
+ public boolean isUploading() {
+ return isUploading;
+ }
+
+ /**
+ * Gets read bytes of the file currently being uploaded.
+ *
+ * @return bytes
+ */
+ public long getBytesRead() {
+ return totalBytes;
+ }
+
+ /**
+ * Returns size of file currently being uploaded. Value sane only during
+ * upload.
+ *
+ * @return size in bytes
+ */
+ public long getUploadSize() {
+ return contentLength;
+ }
+
+ /**
+ * Sets listener to track progress of upload.
+ *
+ * @param progressListener
+ */
+ public void setProgressListener(ProgressListener progressListener) {
+ this.progressListener = progressListener;
+ }
+
+ /**
+ * ProgressListener receives events to track progress of upload.
+ */
+ public interface ProgressListener {
+ /**
+ * Updates progress to listener
+ *
+ * @param readBytes
+ * bytes transferred
+ * @param contentLength
+ * total size of file currently being uploaded, -1 if unknown
+ */
+ public void updateProgress(long readBytes, long contentLength);
+ }
}