package fr.lteconsulting.hexa.client.ui.uploadjs;
import java.util.ArrayList;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import com.google.gwt.core.client.JavaScriptException;
public class FileUploader
{
public interface Callback
{
void onStart();
void onProgress( int percentage, float speed, String response );
}
public void uploadFile( String url, Map<String, String> parameters, String name, File file, Callback callback )
{
tasks.add( new UploadTask( url, parameters, name, file, callback ) );
processNextTask();
}
class UploadTask
{
UploadTask( String url, Map<String, String> parameters, String name, File file, Callback callback )
{
this.url = url;
this.parameters = parameters;
this.name = name;
this.file = file;
this.callback = callback;
}
String url;
String name;
File file;
Map<String, String> parameters;
Callback callback;
void launch()
{
file.getAsBinary( new File.Callback()
{
public void onDataReady( String data )
{
realUpload( data );
}
} );
}
void realUpload( Object binaryData )
{
String boundary = "AJAX------" + Math.random() + "" + new Date().getTime();
final XMLHttpRequestEx req = XMLHttpRequestEx.create();
req.open( "POST", url );
req.setRequestHeader( "Content-Type", "multipart/form-data; boundary=" + boundary );
String CRLF = "\r\n";
String data = "--" + boundary + CRLF;
data += "Content-Disposition: form-data; ";
data += "name=\"" + name + "\"; ";
data += "filename=\"" + file.getFileName() + "\"; " + CRLF;
data += "Content-Type: " + file.getMimeType();
data += CRLF + CRLF;
data += binaryData + CRLF;
if( parameters != null )
{
for( Entry<String, String> e : parameters.entrySet() )
{
data += "--" + boundary + CRLF;
data += "Content-Disposition: form-data; ";
data += "name=\"" + e.getKey() + "\"" + CRLF + CRLF;
data += e.getValue() + CRLF;
}
}
data += "--" + boundary + "--" + CRLF;
try
{
final TransfertSpeedCalculator transfertSpeedCalculator = new TransfertSpeedCalculator();
transfertSpeedCalculator.startTransfert( data.length() );
callback.onStart();
req.sendAsBinary( data, new XMLHttpRequestEx.Callback()
{
@Override
public void onProgress( int percentage )
{
float speed = transfertSpeedCalculator.getSpeed( percentage );
callback.onProgress( percentage, speed, req.getResponseText() );
if( percentage < 0 || percentage == 100 )
{
currentTask = null;
processNextTask();
}
}
} );
}
catch( JavaScriptException e )
{
callback.onProgress( -1, 0, null );
currentTask = null;
processNextTask();
}
}
}
UploadTask currentTask = null;
ArrayList<UploadTask> tasks = new ArrayList<UploadTask>();
void processNextTask()
{
if( currentTask != null )
return;
if( tasks.isEmpty() )
return;
currentTask = tasks.remove( 0 );
currentTask.launch();
}
}
class TransfertSpeedCalculator
{
int dataSize;
long startTime;
public TransfertSpeedCalculator()
{
}
public void startTransfert( int dataSize )
{
this.dataSize = dataSize;
startTime = new Date().getTime();
}
public float getSpeed( int percentage )
{
if( percentage <= 0 )
return 0;
int bytesTransferred = (dataSize * percentage) / 100;
long transfertTime = new Date().getTime() - startTime;
if( transfertTime == 0 )
return 0; // prevent divide by zero
float coef = 1000.0f / 1024.0f;
float speed = coef * ((float) (bytesTransferred) / (float) (transfertTime)); // en
// ko/s
return speed;
}
}