diff --git a/.classpath b/.classpath index 0136fe4..8a93da0 100644 --- a/.classpath +++ b/.classpath @@ -8,5 +8,8 @@ + + + diff --git a/.project b/.project index fb58de7..c932ca6 100644 --- a/.project +++ b/.project @@ -5,15 +5,27 @@ + + org.eclipse.wst.common.project.facet.core.builder + + + org.eclipse.jdt.core.javabuilder + + org.eclipse.wst.validation.validationbuilder + + + + org.eclipse.wst.common.modulecore.ModuleCoreNature org.eclipse.jem.workbench.JavaEMFNature org.eclipse.jdt.core.javanature org.eclipse.jem.beaninfo.BeanInfoNature + org.eclipse.wst.common.project.facet.core.nature diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..139d88b --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Mon Aug 16 22:05:56 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..92485e5 --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,6 @@ + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..126f829 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/libs/commons-fileupload-1.2.1.jar b/libs/commons-fileupload-1.2.1.jar new file mode 100644 index 0000000..aa209b3 Binary files /dev/null and b/libs/commons-fileupload-1.2.1.jar differ diff --git a/libs/commons-io-1.4.jar b/libs/commons-io-1.4.jar new file mode 100644 index 0000000..133dc6c Binary files /dev/null and b/libs/commons-io-1.4.jar differ diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5e94951 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/src/zutil/StringUtil.java b/src/zutil/StringUtil.java index 35a0a0c..dcea12a 100644 --- a/src/zutil/StringUtil.java +++ b/src/zutil/StringUtil.java @@ -6,6 +6,7 @@ package zutil; * @author Ziver * */ public class StringUtil { + public static final String[] sizes = new String[]{"YB", "ZB", "EB", "PB", "TB", "GB", "MB", "kB", "B"}; /** * Present a size (in bytes) as a human-readable value @@ -14,7 +15,6 @@ public class StringUtil { * @return string */ public static String formatBytesToString(long bytes){ - String[] sizes = new String[]{"YB", "ZB", "EB", "PB", "TB", "GB", "MB", "kB", "B"}; int total = sizes.length-1; double value = bytes; @@ -22,7 +22,7 @@ public class StringUtil { value /= 1024; } - value = (double)( (int)(value*100) )/100; + value = (double)( (int)(value*10) )/10; return value+" "+sizes[total]; } diff --git a/src/zutil/jee/upload/AjaxFileUpload.java b/src/zutil/jee/upload/AjaxFileUpload.java new file mode 100644 index 0000000..accb036 --- /dev/null +++ b/src/zutil/jee/upload/AjaxFileUpload.java @@ -0,0 +1,235 @@ +package zutil.jee.upload; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemHeaders; +import org.apache.commons.fileupload.FileItemHeadersSupport; +import org.apache.commons.fileupload.FileItemIterator; +import org.apache.commons.fileupload.FileItemStream; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.util.Streams; + +import zutil.FileUtil; +import zutil.StringUtil; +import zutil.jee.upload.FileUploadListener.Status; +import zutil.log.LogUtil; +import zutil.parser.json.JSONNode; +import zutil.parser.json.JSONWriter; +import zutil.parser.json.JSONNode.JSONType; + +/** + * + * Example web.xml: + * <servlet> + * <servlet-name>Upload</servlet-name> + * <servlet-class>zall.util.AjaxFileUpload</servlet-class> + * <init-param> + * <param-name>JAVASCRIPT</param-name> + * <param-value>{FILE_PATH}</param-value> + * </init-param> + * <init-param> + * <param-name>TEMP_PATH</param-name> + * <param-value>SYSTEM|SERVLET|{PATH}</param-value> + * </init-param> + * </servlet> + * + * + * HTML Header: + * <script type='text/javascript' src='{PATH_TO_SERVLET}?js'></script> + * + * + * HTML Body: + * <FORM id="AjaxFileUpload"> + * <input type="file" multiple name="file" /> + * </FORM> + * <UL id="UploadQueue"></UL> + * + * + * + * @author Ziver + * + */ +public abstract class AjaxFileUpload extends HttpServlet { + public static final Logger logger = LogUtil.getLogger(); + private static final long serialVersionUID = 1L; + + public static final String SESSION_FILEUPLOAD_LISTENER = "FILEUPLOAD_LISTENER"; + public static final String JAVASCRIPT_FILE = "zutil/jee/upload/AjaxFileUpload.js"; + + public static File TEMPFILE_PATH = null; + public static String JAVASCRIPT = ""; + + public void init(ServletConfig config) throws ServletException { + try { + // Read the javascript file to memory + String path = JAVASCRIPT_FILE; + if(config.getInitParameter("JAVASCRIPT") != null) + path = config.getInitParameter("JAVASCRIPT"); + JAVASCRIPT = FileUtil.getContent( FileUtil.findURL(path) ); + + // Read temp dir + if(config.getInitParameter("TEMP_PATH") != null){ + if( config.getInitParameter("TEMP_PATH").equalsIgnoreCase("SYSTEM") ) + TEMPFILE_PATH = new File( System.getProperty("java.io.tmpdir") ); + else if( config.getInitParameter("TEMP_PATH").equalsIgnoreCase("SERVLET") ) + TEMPFILE_PATH = (File) config.getServletContext().getAttribute("javax.servlet.context.tempdir"); + else + TEMPFILE_PATH = new File( config.getInitParameter("TEMP_PATH") ); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("unchecked") + protected void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + PrintWriter out = response.getWriter(); + if(request.getParameter("js") != null){ + response.setContentType("application/x-javascript"); + String tmp = JAVASCRIPT; + tmp = JAVASCRIPT.replaceAll("\\{SERVLET_URL\\}", request.getRequestURI()); + tmp = tmp.replaceAll("\\{BGUPLOAD\\}", "false"); + tmp = tmp.replaceAll("\\{PROGHTML\\}", getProgressHTML()); + out.print(tmp); + return; + } + + response.setContentType("application/json"); + HttpSession session = request.getSession(); + LinkedList list = + (LinkedList)session.getAttribute(SESSION_FILEUPLOAD_LISTENER); + if (list == null) { + out.println("[]"); + return; + } + + // Generate JSON + JSONNode root = new JSONNode( JSONType.List ); + Iterator it = list.iterator(); + while( it.hasNext() ) { + FileUploadListener listener = it.next(); + if( listener.getStatus() == Status.Done || listener.getStatus() == Status.Error ){ + if( listener.getTime() + 5000 < System.currentTimeMillis() ){ + it.remove(); + } + } + + JSONNode node = new JSONNode( JSONType.Map ); + node.add("id", listener.getID()); + node.add("filename", listener.getFilename()); + node.add("percent", listener.getPercentComplete()); + node.add("uploaded", StringUtil.formatBytesToString( listener.getBytesRead() )); + node.add("total", StringUtil.formatBytesToString( listener.getContentLength() )); + node.add("speed", StringUtil.formatBytesToString( listener.getSpeed() )+"/s"); + node.add("status", listener.getStatus().toString()); + root.add(node); + } + + // Write to the user + JSONWriter json_out = new JSONWriter( out ); + json_out.write(root); + } + + + + @SuppressWarnings("unchecked") + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException { + + FileUploadListener listener = new FileUploadListener(); + try { + // Initiate list and HashMap that will contain the data + HashMap fields = new HashMap(); + ArrayList files = new ArrayList(); + + // Add the listener to the session + HttpSession session = request.getSession(); + LinkedList list = + (LinkedList)session.getAttribute(SESSION_FILEUPLOAD_LISTENER); + if(list == null){ + list = new LinkedList(); + session.setAttribute(SESSION_FILEUPLOAD_LISTENER, list); + } + list.add(listener); + + // Create a factory for disk-based file items + DiskFileItemFactory factory = new DiskFileItemFactory(); + if(TEMPFILE_PATH != null) + factory.setRepository( TEMPFILE_PATH ); + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(factory); + upload.setProgressListener( listener ); + // Set overall request size constraint + //upload.setSizeMax(yourMaxRequestSize); + + // Parse the request + FileItemIterator it = upload.getItemIterator( request ); + while( it.hasNext() ) { + FileItemStream item = it.next(); + listener.setFileName( item.getName() ); + FileItem fileItem = factory.createItem(item.getFieldName(), + item.getContentType(), item.isFormField(), item.getName()); + // Read the file data + Streams.copy(item.openStream(), fileItem.getOutputStream(), true); + if (fileItem instanceof FileItemHeadersSupport) { + final FileItemHeaders fih = item.getHeaders(); + ((FileItemHeadersSupport) fileItem).setHeaders(fih); + } + + //Handle the item + if(fileItem.isFormField()){ + fields.put( fileItem.getFieldName(), fileItem.getString()); + } + else{ + files.add( fileItem ); + logger.info("Recieved file: "+fileItem.getName()+" ("+StringUtil.formatBytesToString( fileItem.getSize() )+")"); + } + } + // Process the upload + listener.setStatus( Status.Processing ); + handleUpload( fields, files ); + // Done + listener.setStatus( Status.Done ); + response.getWriter().print("OK"); + } catch (Exception e) { + e.printStackTrace(); + listener.setStatus(Status.Error); + } + } + + /** + * @return the HTML for the progress bar. Special ID's: + *
-filename = String + *
-progress = percent + *
-total = String + *
-uploaded = String + *
-status = String (Uploading, Initializing etc) + *
-speed = String + */ + public abstract String getProgressHTML(); + + /** + * Handle the uppload + */ + public abstract void handleUpload(Map fields, List files); +} diff --git a/src/zutil/jee/upload/AjaxFileUpload.js b/src/zutil/jee/upload/AjaxFileUpload.js new file mode 100644 index 0000000..46c89e9 --- /dev/null +++ b/src/zutil/jee/upload/AjaxFileUpload.js @@ -0,0 +1,97 @@ +/* Values: + * Servlet url(String) = SERVLET_URL + * Background upload(boolean) = BGUPLOAD + * Queue item HTML(String) = PROGHTML + */ +var upload_index = 0; +var upload_update = false; + +// Autostart +jQuery(document).ready(function(){ + initUpload(); + updateUploadStatus() +}); + +/* Initiates a new upload */ +function initUpload(){ + var name = "uploadFrame_"+upload_index; + + // Add iframe + jQuery("body").append(""); + + // Init form settings + var form = jQuery("#AjaxFileUpload"); + //form.attr("encoding", "multipart/form-data"); + form.attr("enctype", "multipart/form-data"); + form.attr("method", "post"); + form.attr("target", name); + form.attr("action", "{SERVLET_URL}"); + form.bind('submit', startUpload ); + //form.attr("onSubmit", "startUpload()"); + + // reset the form + jQuery("#AjaxFileUpload").each(function(){ + this.reset(); + }); + + upload_index++; +} + +function startUpload(){ + if(!upload_update) + setTimeout("updateUploadStatus()", 500); + + // Init new upload + setTimeout("initUpload()", 500); +} + + +function updateUploadStatus(){ + jQuery.ajax({ + url: "{SERVLET_URL}", + cache: false, + dataType: 'json', + success: function(data){ + // Update + upload_update = true; + if(data == null || data.length == 0){ + upload_update = false; + } + else setTimeout("updateUploadStatus()", 1000); + + // Request upload info + jQuery.each(data, function(index,item){ + // add new list item if needed + if( jQuery("#UploadQueue #"+item.id).size() == 0){ + $("#UploadQueue").append("
  • {PROGHTML}
  • "); + } + // Update data + if(jQuery("#UploadQueue #"+item.id+" .filename").size() > 0) + jQuery("#UploadQueue #"+item.id+" .filename").html( item.filename ); + if(jQuery("#UploadQueue #"+item.id+" .progress").size() > 0) + jQuery("#UploadQueue #"+item.id+" .progress").animate({width: item.percent+"%"}, 'slow'); + //jQuery("#UploadQueue #"+item.id+" #progress").css("width", item.percent+"%"); + if(jQuery("#UploadQueue #"+item.id+" .total").size() > 0) + jQuery("#UploadQueue #"+item.id+" .total").html( item.total ); + if(jQuery("#UploadQueue #"+item.id+" .uploaded").size() > 0) + jQuery("#UploadQueue #"+item.id+" .uploaded").html( item.uploaded ); + if(jQuery("#UploadQueue #"+item.id+" .speed").size() > 0) + jQuery("#UploadQueue #"+item.id+" .speed").html( item.speed ); + if(jQuery("#UploadQueue #"+item.id+" .status").size() > 0) + jQuery("#UploadQueue #"+item.id+" .status").html( item.status ); + + // remove li when done + if( item.status == "Done" ){ + jQuery("#UploadQueue #"+item.id).delay(5000).fadeOut("slow", function(){ + jQuery(this).remove(); + }); + //jQuery("#UploadQueue #"+item.id).attr("id", "del"); + } + }); + }, + error: function(request, textStatus){ + alert(textStatus); + } + }); +} \ No newline at end of file diff --git a/src/zutil/jee/upload/FileUploadListener.java b/src/zutil/jee/upload/FileUploadListener.java new file mode 100644 index 0000000..415bd02 --- /dev/null +++ b/src/zutil/jee/upload/FileUploadListener.java @@ -0,0 +1,110 @@ +package zutil.jee.upload; + +import org.apache.commons.fileupload.ProgressListener; + + +/** + * This is a File Upload Listener that is used by Apache + * Commons File Upload to monitor the progress of the + * uploaded file. + */ +public class FileUploadListener implements ProgressListener{ + private static final long serialVersionUID = 1L; + public static enum Status{ + Initializing, + Uploading, + Processing, + Done, + Error + } + + private String id; + private volatile String filename; + private volatile long bytes = 0l; + private volatile long length = 0l; + private volatile int item = 0; + private volatile Status status; + private volatile long time; + + // Speed + private volatile int speed; + private volatile long speedRead; + private volatile long speedTime; + + public FileUploadListener(){ + id = ""+(int)(Math.random()*Integer.MAX_VALUE); + status = Status.Initializing; + } + + public void update(long pBytesRead, long pContentLength, int pItems) { + if(pContentLength < 0) this.length = pBytesRead; + else this.length = pContentLength; + this.bytes = pBytesRead; + this.item = pItems; + + // Calculate Speed + if(speedTime == 0 || speedTime+1000 + + + + + + +
    + + +
    +
      +
    • +
      + + Test + +
      +
    • +
    + + \ No newline at end of file