blob: fe59b274a9ad08e317a34f6ad0f083cb17ee8c75 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 EclipseSource and others.
* 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:
* EclipseSource - initial API and implementation
******************************************************************************/
package org.eclipse.rap.rwt.supplemental.fileupload.internal;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadHandler;
import org.eclipse.rap.rwt.supplemental.fileupload.FileUploadReceiver;
final class FileUploadProcessor {
private final FileUploadHandler handler;
private final FileUploadTracker tracker;
FileUploadProcessor( FileUploadHandler handler ) {
this.handler = handler;
tracker = new FileUploadTracker( handler );
}
void handleFileUpload( HttpServletRequest request, HttpServletResponse response )
throws IOException
{
try {
DiskFileItem fileItem = readUploadedFileItem( request );
if( fileItem != null ) {
tracker.setContentType( fileItem.getContentType() );
tracker.setFileName( stripFileName( fileItem.getName() ) );
FileUploadReceiver receiver = handler.getReceiver();
receiver.receive( fileItem.getInputStream() );
tracker.handleFinished();
} else {
String errorMessage = "No file upload data found in request";
tracker.setException( new Exception( errorMessage ) );
tracker.handleFailed();
response.sendError( HttpServletResponse.SC_BAD_REQUEST, errorMessage );
}
} catch( Exception exception ) {
// Note: Apache fileupload 1.2 will throw an exception after the upload is finished.
// Therefore we handle it in the progress listener and ignore this kind of exceptions here
// https://issues.apache.org/jira/browse/FILEUPLOAD-145
if( exception.getClass() != FileSizeLimitExceededException.class ) {
tracker.setException( exception );
tracker.handleFailed();
}
response.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, exception.getMessage() );
}
}
private DiskFileItem readUploadedFileItem( HttpServletRequest request )
throws FileUploadException
{
ServletFileUpload upload = createUpload();
DiskFileItem result = null;
List uploadedItems = upload.parseRequest( request );
// TODO [rst] Support multiple fields in multipart message
if( uploadedItems.size() > 0 ) {
// TODO [rst] Upload fails if the file is not the first field
DiskFileItem fileItem = ( DiskFileItem )uploadedItems.get( 0 );
// Don't check for file size == 0 because this would prevent uploading empty files
if( !fileItem.isFormField() ) {
result = fileItem;
}
}
return result;
}
private ServletFileUpload createUpload() {
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload result = new ServletFileUpload( factory );
long maxFileSize = getMaxFileSize();
result.setFileSizeMax( maxFileSize );
result.setSizeMax( maxFileSize == -1 ? -1 : maxFileSize + 1000 );
ProgressListener listener = createProgressListener( maxFileSize );
result.setProgressListener( listener );
return result;
}
private ProgressListener createProgressListener( final long maxFileSize ) {
ProgressListener result = new ProgressListener() {
public void update( long bytesRead, long contentLength, int item ) {
// Note: Apache fileupload 1.2 will throw an exception after the upload is finished.
// So we handle the file size violation as best we can from here.
// https://issues.apache.org/jira/browse/FILEUPLOAD-145
if( maxFileSize != -1 && contentLength > maxFileSize ) {
tracker.setException( new Exception( "File exceeds maximum allowed size." ) );
tracker.handleFailed();
} else {
tracker.setContentLength( contentLength );
tracker.setBytesRead( bytesRead );
tracker.handleProgress();
}
}
};
return result;
}
private long getMaxFileSize() {
// TODO [rst] Add configuration option
return -1;
}
private static String stripFileName( String name ) {
String result = name;
int lastSlash = result.lastIndexOf( '/' );
if( lastSlash != -1 ) {
result = result.substring( lastSlash + 1 );
} else {
int lastBackslash = result.lastIndexOf( '\\' );
if( lastBackslash != -1 ) {
result = result.substring( lastBackslash + 1 );
}
}
return result;
}
}