X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=eclipse%2Frap%2Forg.eclipse.rwt.widgets.upload%2Fsrc%2Forg%2Feclipse%2Frwt%2Fwidgets%2Fupload%2Fservlet%2FFileUploadServiceHandler.java;fp=eclipse%2Frap%2Forg.eclipse.rwt.widgets.upload%2Fsrc%2Forg%2Feclipse%2Frwt%2Fwidgets%2Fupload%2Fservlet%2FFileUploadServiceHandler.java;h=80216ae8b685f7c5cc3713e1225cd3a2d05771a0;hb=65dd9952af869d4eac2b0cd0ca2751e03955638f;hp=0000000000000000000000000000000000000000;hpb=40092fb35537b5bf2833a8ba5fda76ab3807a302;p=lgpl%2Fargeo-commons.git diff --git a/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java new file mode 100644 index 000000000..80216ae8b --- /dev/null +++ b/eclipse/rap/org.eclipse.rwt.widgets.upload/src/org/eclipse/rwt/widgets/upload/servlet/FileUploadServiceHandler.java @@ -0,0 +1,280 @@ +/******************************************************************************* + * Copyright (c) 2002-2006 Innoopract Informationssysteme GmbH. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Innoopract Informationssysteme GmbH - initial API and implementation + ******************************************************************************/ + +package org.eclipse.rwt.widgets.upload.servlet; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.*; + +import org.apache.commons.fileupload.*; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.eclipse.rwt.RWT; +import org.eclipse.rwt.internal.util.URLHelper; +import org.eclipse.rwt.service.IServiceHandler; +import org.eclipse.rwt.widgets.IUploadConfiguration; +import org.eclipse.rwt.widgets.internal.UploadConfiguration; + + +/** + * Handles file uploads and upload progress updates. + *

+ * Implementation note: uploaded files are currently stored in the + * java.io.tmpdir. See + * {@link #handleFileUpload(HttpServletRequest, FileUploadStorageItem)} on + * how to change this. + * + * @author stefan.roeck + */ +public class FileUploadServiceHandler implements IServiceHandler { + + private static final String REQUEST_WIDGET_ID = "widgetId"; + private static final String REQUEST_PROCESS_ID = "processId"; + private static final String XML_HEAD = ""; + + /** + * Holds configuration data for the upload widget. + */ + private static final IUploadConfiguration uploadConfiguration = new UploadConfiguration(); + + /** + * Requests to this service handler without a valid session id are ignored for + * security reasons. The same applies to request with widgetIds which haven't been + * registered at the session singleton {@link FileUploadStorage}. + */ + public void service() throws IOException, ServletException { + + final HttpServletRequest request = RWT.getRequest(); + final String widgetId = request.getParameter( REQUEST_WIDGET_ID ); + final String uploadProcessId = request.getParameter( REQUEST_PROCESS_ID ); + final HttpSession session = request.getSession( false ); + + if( session != null + && widgetId != null + && !"".equals( widgetId ) + && uploadProcessId != null + && !"".equals( uploadProcessId ) ) + { + final FileUploadStorage fileUploadStorage = FileUploadStorage.getInstance(); + final FileUploadStorageItem fileUploadStorageItem = fileUploadStorage.getUploadStorageItem( widgetId ); + + // fileUploadStorageItem can be null, if Upload widget is dispsed! + if (ServletFileUpload.isMultipartContent(request)) { + // Handle post-request which contains the file to upload + handleFileUpload( request, fileUploadStorageItem, uploadProcessId ); + } else { + // This is probably a request for updating the progress bar + handleUpdateProgress( fileUploadStorageItem, uploadProcessId ); + } + + } + } + + /** + * Treats the request as a post request which contains the file to be + * uploaded. Uses the apache commons fileupload library to + * extract the file from the request, attaches a {@link FileUploadListener} to + * get notified about the progress and writes the file content + * to the given {@link FileUploadStorageItem} + * @param request Request object, must not be null + * @param fileUploadStorageitem Object where the file content is set to. + * If null, nothing happens. + * @param uploadProcessId Each upload action has a unique process identifier to + * match subsequent polling calls to get the progress correctly to the uploaded file. + * + */ + private void handleFileUpload( final HttpServletRequest request, + final FileUploadStorageItem fileUploadStorageitem, + final String uploadProcessId ) + { + // Ignore upload requests which have no valid widgetId + if (fileUploadStorageitem != null && uploadProcessId != null && !"".equals( uploadProcessId )) { + + // Reset storage item to clear values from last upload process + fileUploadStorageitem.reset(); + + // Create file upload factory and upload servlet + // You could use new DiskFileItemFactory(threshold, location) + // to configure a custom in-memory threshold and storage location. + // By default the upload files are stored in the java.io.tmpdir + final FileItemFactory factory = new DiskFileItemFactory(); + final ServletFileUpload upload = new ServletFileUpload( factory ); + + // apply configuration params + applyConfiguration(upload); + + // Create a file upload progress listener + final ProgressListener listener = new ProgressListener() { + + public void update( final long aBytesRead, + final long aContentLength, + final int anItem ) { + fileUploadStorageitem.updateProgress( aBytesRead, aContentLength ); + } + + }; + // Upload servlet allows to set upload listener + upload.setProgressListener( listener ); + fileUploadStorageitem.setUploadProcessId( uploadProcessId ); + + FileItem fileItem = null; + try { + final List uploadedItems = upload.parseRequest( request ); + // Only one file upload at once is supported. If there are multiple files, take + // the first one and ignore other + if ( uploadedItems.size() > 0 ) { + fileItem = ( FileItem )uploadedItems.get( 0 ); + // Don't check for file size 0 because this prevents uploading new empty office xp documents + // which have a file size of 0. + if( !fileItem.isFormField() ) { + fileUploadStorageitem.setFileInputStream( fileItem.getInputStream() ); + fileUploadStorageitem.setContentType(fileItem.getContentType()); + } + } + } catch( final FileUploadException e ) { + fileUploadStorageitem.setException(e); + } catch( final Exception e ) { + fileUploadStorageitem.setException(e); + } + } + } + + /** + * Applies custom configuration parameters specified by the + * user. + * @param upload The upload handler to which the config is applied. + */ + private void applyConfiguration( final ServletFileUpload upload ) { + upload.setFileSizeMax( getConfiguration().getFileSizeMax() ); + upload.setSizeMax( getConfiguration().getSizeMax() ); + } + + /** + * Treats the request as a get request which is triggered by the + * browser to retrieve the progress state. Gets the registered + * {@link FileUploadListener} from the given {@link FileUploadStorageItem} + * to check the current progress. The result is written to the response + * in an XML format. + *
+ * Note: It is important that a valid response is written in any case + * to let the Browser know, when polling can be stopped. + * @param uploadProcessId + */ + private void handleUpdateProgress( final FileUploadStorageItem fileUploadStorageitem, final String uploadProcessId ) + throws IOException + { + final HttpServletResponse response = RWT.getResponse(); + final PrintWriter out = response.getWriter(); + + final StringBuffer buffy = new StringBuffer( XML_HEAD ); + long bytesRead = 0; + long contentLength = 0; + // Check to see if we've created the listener object yet + response.setContentType( "text/xml" ); + response.setHeader( "Cache-Control", "no-cache" ); + + if( fileUploadStorageitem != null ) { + + if ( uploadProcessId != null && uploadProcessId.equals( fileUploadStorageitem.getUploadProcessId() )) { + + // Get the meta information + bytesRead = fileUploadStorageitem.getBytesRead(); + contentLength = fileUploadStorageitem.getContentLength(); + /* + * XML Response Code + */ + buffy.append( "" ); + buffy.append( bytesRead ); + buffy.append( "" ); + buffy.append( contentLength ); + buffy.append( "" ); + // Check to see if we're done + // Even files with a size of 0 have a content length > 0 + if( contentLength != 0 ) { + if( bytesRead == contentLength ) { + buffy.append( "" ); + } else { + // Calculate the percent complete + buffy.append( "" ); + buffy.append( ( 100 * bytesRead / contentLength ) ); + buffy.append( "" ); + } + } else { + // Contentlength should not be 0, however, send finished to make sure + // the Browser side polling stops. + buffy.append( "" ); + } + } else { + //System.out.println("No match: " + uploadProcessId + " " + fileUploadStorageitem.getUploadProcessId()); + // if the processId doesn't match, return nothing + // which causes the client script to send another + // request after waiting. This could happen, + // if the first GET-request was send, before the + // Upload-POST request arrived. + } + + } else { + // if fileUploadStorageitem is null, the upload widget is disposed + // return "finished" to stop monitoring + buffy.append( "" ); + } + + buffy.append( "
" ); + out.println( buffy.toString() ); + out.flush(); + out.close(); + } + + /** + * Registers this service handler. This method should be called only once. + */ + public static void register() { + final FileUploadServiceHandler instance = new FileUploadServiceHandler(); + final String serviceHandlerId = getServiceHandlerId(); + RWT.getServiceManager().registerServiceHandler(serviceHandlerId, instance); + } + + /** + * Returns a unique id for this service handler class. + */ + private static String getServiceHandlerId() { + final String serviceHandlerId = FileUploadServiceHandler.class.getName(); + return serviceHandlerId; + } + + /** + * Builds a url which points to the service handler and encodes the given parameters + * as url parameters. + */ + public static String getUrl(final String widgetId) { + final StringBuffer url = new StringBuffer(); + url.append(URLHelper.getURLString(false)); + + URLHelper.appendFirstParam(url, REQUEST_PARAM, getServiceHandlerId()); + URLHelper.appendParam(url, REQUEST_WIDGET_ID, widgetId); + + // convert to relative URL + final int firstSlash = url.indexOf( "/" , url.indexOf( "//" ) + 2 ); // first slash after double slash of "http://" + url.delete( 0, firstSlash ); // Result is sth like "/rap?custom_service_handler..." + return RWT.getResponse().encodeURL(url.toString()); + } + + /** + * Returns a configuration facade. + */ + public static IUploadConfiguration getConfiguration() { + return uploadConfiguration; + } +}