package com.gwt.ui.client.gwtupld; import java.util.HashMap; import java.util.Map; import com.google.gwt.http.client.URL; import com.google.gwt.json.client.JSONParser; import com.google.gwt.json.client.JSONString; import com.google.gwt.json.client.JSONValue; import com.google.gwt.xhr.client.ReadyStateChangeHandler; import com.google.gwt.xhr.client.XMLHttpRequest; import com.gwt.ui.client.gwtupld.file.File; import com.gwt.ui.client.gwtupld.shr.OnUploadProgressEvent; import com.gwt.ui.client.gwtupld.shr.OnUploadProgressHandler; import com.gwt.ui.client.gwtupld.shr.XMLHttpRequestAdvanced; import com.gwt.ui.client.gwtupld.utils.UUID; /** * Class for uploading files using XHR */ public class UploadHandlerXhr extends UploadHandlerAbstract { private Map<String, File> files; private Map<String, XMLHttpRequest> xhrs; // current loaded size in bytes for each file private Map<String, Integer> loaded; public UploadHandlerXhr(UploadProgressHandlers handlers, Options options) { super(handlers, options); files = new HashMap<String, File>(); xhrs = new HashMap<String, XMLHttpRequest>(); loaded = new HashMap<String, Integer>(); } @Override protected String add(Object o) { final String id = UUID.uuid(); files.put(id, (File)o); return id; } @Override protected String getName(String id) { return files.get(id).getName(); } @Override protected int getSize(String id) { return files.get(id).getSize(); } /** * Sends the file identified by id and additional query params to the server * * @param id file id * @param params params name-value string pairs */ @Override protected String _upload(final String id, Map<String, String> params) { final File file = files.get(id); final String name = getName(id); final long size = getSize(id); loaded.put(id, 0); XMLHttpRequestAdvanced xhr = XMLHttpRequestAdvanced.create(); xhrs.put(id, xhr); xhr.setOnUploadProgress(new OnUploadProgressHandler() { @Override public void onUploadProgress(OnUploadProgressEvent e) { if (e.isLengthComputable()) { loaded.put(id, e.getLoaded()); UploadHandlerXhr.super.progressHandlers.onProgress(id, name, e.getLoaded(), e.getTotal()); } } }); xhr.setOnReadyStateChange(new ReadyStateChangeHandler() { @Override public void onReadyStateChange(XMLHttpRequest xhr) { if (xhr.getReadyState() == XMLHttpRequest.DONE) { onComplete(id, xhr); } } }); // params = params || {}; // params['qqfile'] = name; String queryString = appendParamsToAction(options.getAction(), options.getParams()); xhr.open("POST", queryString); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xhr.setRequestHeader("X-File-Name", URL.encode(name)); xhr.setRequestHeader("Content-Type", "application/octet-stream"); xhr.send(file); log("File with id `" + id + "` was just sent to server"); return null; } @Override protected void _cancel(String id) { progressHandlers.onCancel(id, files.get(id).getName()); files.remove(id); final XMLHttpRequest xhr = xhrs.get(id); if (xhr != null) { xhr.abort(); xhr.clearOnReadyStateChange(); xhrs.remove(id); } } private void onComplete(String id, XMLHttpRequest xhr) { log("File with id `" + id + "` has been successfully uploaded"); if (files.get(id) == null) { // the request was aborted/cancelled return; } String name = getName(id); int size = getSize(id); // TODO: what is it for within `onComplete` progressHandlers.onProgress(id, name, size, size); JSONValue response = new JSONString(""); log("xhr - status is " + xhr.getStatus()); log("xhr - response is " + xhr.getResponseText()); if (xhr.getStatus() == 200) { response = JSONParser.parseStrict(xhr.getResponseText()); } progressHandlers.onComplete(id, name, response); files.remove(id); xhr.clearOnReadyStateChange(); xhrs.remove(id); _dequeue(id); } public native static boolean isSupported() /*-{ var input = document.createElement('input'); input.type = 'file'; return ( 'multiple' in input && typeof File != "undefined" && typeof (new XMLHttpRequest()).upload != "undefined" ); }-*/; }