📄 fileuploadmanagerthread.java
字号:
package wjhk.jupload2.upload;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JProgressBar;
import javax.swing.Timer;
import wjhk.jupload2.exception.JUploadException;
import wjhk.jupload2.filedata.FileData;
import wjhk.jupload2.gui.JUploadPanel;
import wjhk.jupload2.gui.filepanel.FilePanel;
import wjhk.jupload2.gui.filepanel.SizeRenderer;
import wjhk.jupload2.policies.UploadPolicy;
/**
* This class is responsible for managing the upload. At the end of the upload,
* the {@link JUploadPanel#updateButtonState()} is called, to refresh the button
* state. Its job is to: <DIR> <LI>Prepare upload for the file (calls to
* {@link FileData#beforeUpload()} for each file in the file list. <LI>Create
* the thread to send a packet of files. <LI>Prepare the packets, that will be
* red by the upload thread. <LI>Manage the end of upload: trigger the call to
* {@link JUploadPanel#updateButtonState()} and the call to
* {@link UploadPolicy#afterUpload(Exception, String)}. <LI>Manage the 'stop'
* button reaction. </DIR> This class is created by {@link JUploadPanel}, when
* the user clicks on the upload button.
*
* @author etienne_sf
*/
public class FileUploadManagerThread extends Thread implements ActionListener {
// /////////////////////////////////////////////////////////////////////////////////////////
// //////////////////// Possible Status for file upload
// /////////////////////////////////////////////////////////////////////////////////////////
/** Indicates that nothings has begun */
public static final int UPLOAD_STATUS_NOT_STARTED = 1;
/**
* We're sending data to the server, for the file identified by
* numOfFileInCurrentRequest.
*/
public static final int UPLOAD_STATUS_UPLOADING = 2;
/**
* All data for the file identified by numOfFileInCurrentRequest has been
* sent. But the server response has not been received.
*/
public static final int UPLOAD_STATUS_UPLOADED_WAITING_FOR_RESPONSE = 3;
/**
* The upload for the file identified by numOfFileInCurrentRequest is
* finished
*/
public static final int UPLOAD_STATUS_UPLOADED = 4;
// /////////////////////////////////////////////////////////////////////////////////////////
// //////////////////// Possible Status for file upload
// /////////////////////////////////////////////////////////////////////////////////////////
/**
* Contains the date/time (as a long) of the start of the current upload.
* This allows to sum the time of the actual upload, and ignore the time the
* applet is waiting for the server's response. Once the request is
* finished, and the applet waits for the server's response, the duration of
* the sending to the server is added to currentRequestStartTime, and
* currentRequestStartTime is reseted to 0. It's then ready for the next
* upload request.
*/
private long currentRequestStartTime = 0;
/** The current file list. */
private FilePanel filePanel = null;
/**
* The upload thread, that will wait for the next file packet to be ready,
* then send it.
*/
private FileUploadThread fileUploadThread = null;
/**
* Contains the system time of the start of the global upload. This is used
* to calculate the ETA, and display it to the user, on the status bar.
*/
private long globalStartTime = 0;
/** @see UploadPolicy#getMaxChunkSize() */
long maxChunkSize = -1;
/** Contains the sum of the files, ready for upload, and not uploaded yet */
private long nbBytesReadyForUpload = 0;
/**
* Number of files that has been read by the {@link FileUploadThread}
* thread. These files have been read by the {@link #getNextPacket()}
* method.
*/
private int nbFilesBeingUploaded = 0;
/** @see UploadPolicy#getNbFilesPerRequest() */
int nbFilesPerRequest = -1;
/**
* Number of files that are prepared for upload. A file is prepared for
* upload, if the {@link FileData#beforeUpload()} has been called.
*/
private int nbPreparedFiles = 0;
/**
* Number of files that have already been sent. The control on the upload
* success may be done or not. It's used to properly display the progress
* bar.
*/
private int nbSentFiles = 0;
/**
* Number of files that have been successfully uploaded. already been sent.
* The control on the upload success may be done or not. It's used to
* properly display the progress bar.
*/
private int nbSuccessfullyUploadedFiles = 0;
/**
* Indicated the number of bytes that have currently been sent for the
* current file. This allows the management of the progress bar.
*/
private long nbBytesUploadedForCurrentFile = 0;
/**
* Sum of the length for all prepared files. This allow the calculation of
* the estimatedTotalLength.
*
* @see #anotherFileHasBeenSent(FileData)
*/
private long nbTotalNumberOfPreparedBytes = 0;
/**
* During the upload, when uploading several files in one packet, this
* attribute indicates which file is currently being uploaded.
*/
private int numOfFileInCurrentRequest = 0;
/**
* Indicates what is the current file being uploaded, and its upload status.
*/
private int uploadStatus = UPLOAD_STATUS_NOT_STARTED;
/**
* Contains the next packet to upload.
*
* @see #getNextPacket()
*/
private UploadFileData[] nextPacket = null;
/**
* The {@link JUploadPanel} progress bar, to follow the file preparation
* progress.
*/
private JProgressBar preparationProgressBar = null;
/**
* The {@link JUploadPanel} progress bar, to follow the upload of the
* prepared files to the server.
*/
private JProgressBar uploadProgressBar = null;
/**
* Indicates whether the upload is finished or not. Passed to true as soon
* as one of these conditions becomes true: <DIR> <LI>All files are uploaded
* (in the {@link #currentRequestIsFinished(UploadFileData[])} method) <LI>
* An exception occurs (in the {@link #setUploadException(JUploadException)}
* method) <LI>The user stops the upload (in the {@link #stopUpload()}
* method) </DIR>
*/
private boolean uploadFinished = false;
/**
* Contains the time of the actual start of upload. Doesn't take into
* account the time for preparing files.
*/
private long uploadStartTime = 0;
/**
* If set to 'true', the thread will stop the current upload. This attribute
* is not private as the {@link UploadFileData} class us it.
*
* @see UploadFileData#uploadFile(java.io.OutputStream, long)
*/
private boolean stop = false;
/** Thread Exception, if any occurred during upload. */
private JUploadException uploadException = null;
/**
* Contains the sum of the upload duration for all requests. For instance,
* if sending in 10 chunks one big file, the uploadDuration contains the sum
* of the sending of these 10 request to the server. This allows to
* calculate the true upload speed, and ignore the time we'll wait for the
* server's response.
*/
private long uploadDuration = 0;
/** Current number of bytes that have been uploaded. */
private long nbUploadedBytes = 0;
/** A shortcut to the upload panel */
private JUploadPanel uploadPanel = null;
/** The current upload policy. */
private UploadPolicy uploadPolicy = null;
/** The list of files to upload */
private UploadFileData[] uploadFileDataArray = null;
// ////////////////////////////////////////////////////////////////////////////
// To follow the upload speed.
// ////////////////////////////////////////////////////////////////////////////
/**
* Used to update the status bar (upload speed, ETA...): 300ms make it
* accurate, and avoid an always changing value.
*/
private Timer timerStatusBar = new Timer(1000, this);
/**
* Used to update the progress: 50ms is nice, as it is fast enough, and
* doesn't make CPU rise to 100%.
*/
private Timer timerProgressBar = new Timer(50, this);
/**
* Standard constructor of the class.
*
* @param uploadPolicy
*/
public FileUploadManagerThread(UploadPolicy uploadPolicy) {
super("FileUploadManagerThread thread");
// General shortcuts on the current applet.
this.uploadPolicy = uploadPolicy;
this.uploadPanel = uploadPolicy.getApplet().getUploadPanel();
this.filePanel = this.uploadPanel.getFilePanel();
this.uploadProgressBar = this.uploadPanel.getUploadProgressBar();
this.preparationProgressBar = this.uploadPanel
.getPreparationProgressBar();
// Let's start the upload thread. It will wait until the first
// packet is ready.
createUploadThread();
// Let's store some upload parameters, to avoid querying all the time.
this.nbFilesPerRequest = this.uploadPolicy.getNbFilesPerRequest();
this.maxChunkSize = this.uploadPolicy.getMaxChunkSize();
// Prepare the list of files to upload. We do this here, to minimize the
// risk of concurrency, if the user drops or pastes files on the applet
// while uploading.
FileData[] fileDataArray = this.uploadPanel.getFilePanel().getFiles();
this.uploadFileDataArray = new UploadFileData[fileDataArray.length];
for (int i = 0; i < this.uploadFileDataArray.length; i += 1) {
this.uploadFileDataArray[i] = new UploadFileData(fileDataArray[i],
this, this.uploadPolicy);
}
}
/**
* The heart of the program. This method prepare the upload, then calls
* doUpload for each HTTP request.
*
* @see java.lang.Thread#run()
*/
@Override
final public void run() {
try {
this.uploadPolicy.displayDebug(
"Start of the FileUploadManagerThread", 5);
// Let's let the current upload policy have any preparation work
this.uploadPolicy.beforeUpload();
// The upload is started. Let's change the button state.
this.uploadPanel.updateButtonState();
// Let's prepare the progress bar, to display the current upload
// stage.
initProgressBar();
// Create a timer, to update the status bar.
this.timerProgressBar.start();
this.timerStatusBar.start();
this.uploadPolicy.displayDebug("Timer started", 50);
// We have to prepare the files, then to create the upload thread
// for
// each file packet.
prepareFiles();
// The thread upload may need some information about the current
// one, like ... knowing that upload is actually finished (no more
// file to send).
while (this.fileUploadThread != null
&& this.fileUploadThread.isAlive()
&& this.nbSuccessfullyUploadedFiles < this.uploadFileDataArray.length
&& this.getUploadException() == null && !this.stop) {
try {
this.uploadPolicy.displayDebug(
"Waiting for fileUploadThread to die", 10);
this.fileUploadThread.join();
} catch (InterruptedException e) {
// This should not occur, and should not be a problem. Let's
// trace a warning info.
this.uploadPolicy
.displayWarn("An InterruptedException occured in FileUploadManagerThread.run()");
}
}
// Let's restore the button state.
this.uploadPanel.updateButtonState();
this.uploadPolicy.getApplet().getAppletContext().showStatus("");
this.uploadPolicy.getApplet().getUploadPanel().getStatusLabel()
.setText("");
// If no error occurs, we tell to the upload policy that a
// successful
// upload has been done.
if (getUploadException() == null) {
this.uploadPolicy
.displayInfo("Upload finished normally. "
+ this.uploadFileDataArray.length
+ " file(s) uploaded in "
+ (int) ((System.currentTimeMillis() - this.globalStartTime) / 1000)
+ " seconds. Average upload speed: "
+ (int) (this.nbUploadedBytes / this.uploadDuration)
+ " (kbytes/s)");
try {
this.uploadPolicy.afterUpload(this.getUploadException(),
this.fileUploadThread.getResponseMsg());
} catch (JUploadException e1) {
this.uploadPolicy.displayErr(
"error in uploadPolicy.afterUpload (JUploadPanel)",
e1);
}
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -