Package wjhk.jupload2.upload Description
This package contains the code that actually executes the upload (see below for a full description of the way the upload
is executed in the JUpload code).
It is structured around these main items:
FileUploadManagerThread: The main class. It controls the execution of
the upload, manages the file preparation, the progress bar, the possible exceptions...
FileUploadThread: The interface of the class the execute the successives requests
to the server. The following class implements this interface:
DefaultFileUploadThread is an abstract class, the provides the global
upload mechanism to send one packet of files to the server. The packet is created by FileUploadManagerThread,
according to the current upload policy, with parameters like: maxChunkSize and nbFilesPerRequest. All protocol
specific methods are implemented in the following implementation, depending on the applet parameter postURL:
FileUploadThreadHTTP executes uploads to an HTTP server (http, https,
proxy or not...), by using POST requests. It implements the abstract methods of DefaultFileUploadThread.
FileUploadThreadFTP is the implementation for FTP servers
UploadFileData is an implementation of the
wjhk.jupload2.filedata.FileData interface, to add the
uploadFile(OutputStream, long) method,
which sends the file bytes to the server.
The wjhk.jupload2.upload.helper package offers various utilities to manage the upload.
How works the upload
Here is a description of what occurs, when the user clicks on the 'upload' button, on the applet, or when the
applet startUpload() method is called by javascript:
The JUploadPanel.doStartUpload() starts the job
It calls the UploadPolicy.beforeUpload() method. If this method
returns false, the process stops here.
It then creates and starts the FileUploadManagerThread thread. This thread is responsible to throw all necessary
actions to execute the upload
The fileUploadManagerThread creates the necessary queues and threads (see below)
It then waits for the upload to finish, by comparing the total number of files to upload to the number of uploaded
files, after each successful upload.
The upload is done by these threads:
FileUploadManagerThread: The main thread of the upload, does these actions:
creation and start the queues described below.
creation and start the threads described below.
waiting for the upload to be finished
updating the upload progress bar
maintain the end of upload flag (with the isUploadFinished() method)
FilePreparationThread: This thread:
reads the list of files, from the FilePanel,
prepares each file for upload, by calling the FileData.beforeUpload() method.
manages exceptions that could occurs here. If one occurs, the user is asked if he want to go on with upload.
put the prepared file on the preparedFileQueue, if everything is ok.
put a UploadFileDataPoisonned, to tell the PacketPreparationThread
that the last file was sent.
contains the reference of the number of files to upload (as some files may be in error, while the upload goes on).
PacketConstructionThread: This thread is responsible for grouping the
files in packet of files, that will be sent in one request to the server. It:
reads the files in the preparedFileQueue
checks if it can be added to the current packet.
put the packet in the packetQueue as soon as a packet is ready (or when the upload is finished)
put a UploadFilePacketPoisonned, to tell the FileUploadThread
that the last packet was sent.
adds the file to the current packet.
FileUploadThread: This interface is implemented by these classes:
DefaultFileUploadThread is an abstract
class that contains all non protocol-specific code. The FileUploadThreadFTP and
FileUploadThreadHTTP class implements the protocol-specific treatements, mainly:
build the request and read the server response. These classes do these actions:
Reads the next packet in the packetQueue
Checks if the upload is in chunked mode or not. Chunk mode is activated when the packet size is bigger than the
maxChunkSize applet. There must be only one file in the packet.
Calls the DefaultFileUploadThread.beforeRequest(UploadFilePacket)
method, for any request preparation (server connection...)
Calls the DefaultFileUploadThread.startRequest(long, boolean, int, boolean)
method, for headers that need to be sent before the first file.
[Non chunked mode] Loops throught the files in the packet:
Calls the beforeFile(UploadFilePacket, UploadFileData)
Calls the UploadFileData.uploadFile(OutputStream, long) to send the bytes for the already prepared files to the server.
Calls the afterFile(UploadFileData)
[Chunked mode] Loops throught the chunks for the unique file in the packet:
Calls the beforeFile(UploadFilePacket, UploadFileData)
Calls the UploadFileData.uploadFile(OutputStream, long) to send the bytes for the current chunk of the already prepared
files to the server.
Calls the afterFile(UploadFileData)
Calls the finishRequest() method, to clean any
resources about this request.
The UploadPolicy.checkUploadSuccess(int, String, String)
is called after each request to the server, to check that the server response contains the relevant success string.
It also checks if an error occurs (and then displays the message to the user). In this case, the
FileUploadManagerThread.setUploadException(JUploadException)
is called. This stops the upload. All threads will quit.
Calls the cleanRequest() method, to clean any resources
used by this request.
Calls the cleanAll() method when the upload is finished,
to clean any global resource for the upload.
The resume facility
When a network error occurs during upload, the applet can have some retries to the server. These retries can be automatic
or manually controlled. When an retries occurs, the whole packet is resent. That is: the apply re-execute the request that
failed. For chunk upload, all packets are re-sent, starting from chunk number 1.
Impacts:
- The FileData.afterUpload() can only be called once the whole request is a success or a failure without retry. That is: the afterUpload
is called after catching the exception, that may be resumed.
--> The call to FileData.afterUpload() should be moved from doNonChunkedUpload() and doChunkedUpload() to doUpload, in a
new finally block, in a finally block.
The file information, send along with the file data
During the upload, the applet also sends metadata about the file. They are sent as POST attributes. These attribute are suffixed by the file index, starting by 0.
For instance, the mimetype for the first uploaded file is sent in the 'mimetype0' post parameter.
You can find samples in Java and PHP, here : ./src/site/resources/samples.java/parseRequest.jsp and ./src/site/resources/samples.PHP/after_upload.php (and jupload.php)
Here are they:
- mimetype: the mimetype for the file. This mime type is only sent from windows computers. It is based on the file extension. The mime type is defined
by a transcoding property file (see ./src/resources/conf/mimetypes.properties)
- pathinfo: the global path of the uploaded file, in the local filesystem
- relpathinfo: the path of the uploaded file, relative to the upload root. The upload root is the most profound folder, common to all files. For instance,
the root when uploaded /tmp/test/toto/bla and /tmp/test/titi/blabla is /tmp/test.
- filemodificationdate: the last modification dte of the source file
- md5sum: the md5sum of the file, for integrity test. Please read the doc for the sendMD5Sum applet parameter.
You can get the file length, by the standard way of manipulate uploaded files. See the samples for details.