📄 defaultfileuploadthread.java
字号:
if (this.filesToUpload != null) {
this.uploadPolicy.displayDebug("Before do upload", 5);
// Let's go to work.
doUpload();
this.uploadPolicy.displayDebug("After do upload", 5);
} else {
try {
// We wait a little. If a file is prepared in the
// meantime, this thread is notified. The wait duration,
// is just to be sure to go and see if there is still
// some work from time to time.
sleep(200);
} catch (InterruptedException e) {
// Nothing to do. We'll just take a look at the loop
// condition.
}
}
}
} catch (JUploadException e) {
this.fileUploadManagerThread.setUploadException(e);
}
this.uploadPolicy.displayDebug("End of the FileUploadThread", 5);
}// run
/**
* Actual execution file(s) upload. It's called by the run methods, once for
* all files, or file by file, depending on the UploadPolicy. The list of
* files to upload is stored in the {@link #filesToUpload} array.<BR>
* This method is called by the run() method. The prerequisite about the
* filesToUpload array are: <DIR> <LI>If the sum of contentLength for the
* files in the array is more than the maxChunkSize, then
* nbFilesToUploadParam is one. <LI>The number of elements in filesToUpload
* is less (or equal) than the nbMaxFilesPerUpload. </DIR>
*
* @throws JUploadException
*/
final private void doUpload() throws JUploadException {
boolean bChunkEnabled = false;
long totalContentLength = 0;
long totalFileLength = 0;
// We are about to start a new upload.
this.fileUploadManagerThread.setUploadStatus(0,
FileUploadManagerThread.UPLOAD_STATUS_UPLOADING);
// Prepare upload, for all files to be uploaded.
beforeRequest();
for (int i = 0; i < this.filesToUpload.length
&& !this.fileUploadManagerThread.isUploadStopped(); i++) {
// Total length, for HTTP upload.
totalContentLength += this.filesToUpload[i].getUploadLength();
totalContentLength += getAdditionnalBytesForUpload(i);
// Total file length: used to manage the progress bar (we don't
// follow the bytes uploaded within headers and forms).
totalFileLength += this.filesToUpload[i].getUploadLength();
this.uploadPolicy.displayDebug("file "
+ (this.fileUploadManagerThread.getNbUploadedFiles() + i)
+ ": content=" + this.filesToUpload[i].getUploadLength()
+ " bytes, getAdditionnalBytesForUpload="
+ getAdditionnalBytesForUpload(i) + " bytes", 50);
}// for
// Ok, now we check that the totalContentLength is less than the chunk
// size.
if (totalFileLength >= this.maxChunkSize) {
// hum, hum, we have to download file by file, with chunk enabled.
// This a prerequisite of this method.
if (this.filesToUpload.length > 1) {
this.fileUploadManagerThread
.setUploadException(new JUploadException(
"totalContentLength >= chunkSize: this.filesToUpload.length should be 1 (doUpload)"));
}
bChunkEnabled = true;
}
// Now, we can actually do the job. This is delegate into smaller
// method, for easier understanding.
if (bChunkEnabled) {
doChunkedUpload(totalContentLength, totalFileLength);
} else {
doNonChunkedUpload(totalContentLength, totalFileLength);
}
this.fileUploadManagerThread
.currentRequestIsFinished(this.filesToUpload);
// We are finished with this packet. Let's display it.
this.fileUploadManagerThread.setUploadStatus(this.filesToUpload.length,
FileUploadManagerThread.UPLOAD_STATUS_UPLOADED);
}
/**
* Execution of an upload, in chunk mode. This method expects that the
* {@link #filesToUpload} array contains only one line.
*
* @throws JUploadException When any error occurs, or when there is more
* than one file in {@link #filesToUpload}.
*/
final private void doChunkedUpload(final long totalContentLength,
final long totalFileLength) throws JUploadException {
boolean bLastChunk = false;
int chunkPart = 0;
long contentLength = 0;
long thisChunkSize = 0;
// No more than one file, when in chunk mode.
if (this.filesToUpload.length > 1) {
throw new JUploadException(
"totalContentLength >= chunkSize: this.filesToUpload.length should not be more than 1 (doUpload)");
}
// This while enables the chunk management:
// In chunk mode, it loops until the last chunk is uploaded. This works
// only because, in chunk mode,
// files are uploaded one y one (the for loop within the while loops
// through ... 1 unique file).
// In normal mode, it does nothing, as the bLastChunk is set to true in
// the first test, within the while.
while (!bLastChunk
&& this.fileUploadManagerThread.getUploadException() == null
&& !this.fileUploadManagerThread.isUploadStopped()) {
// Let's manage chunk:
// Files are uploaded one by one. This is checked just above.
chunkPart += 1;
bLastChunk = (contentLength > this.filesToUpload[0]
.getRemainingLength());
// Is this the last chunk ?
if (bLastChunk) {
thisChunkSize = this.filesToUpload[0].getRemainingLength();
} else {
thisChunkSize = this.maxChunkSize;
}
contentLength = thisChunkSize + getAdditionnalBytesForUpload(0);
// Ok, we've prepare the job for chunk upload. Let's do it!
startRequest(contentLength, true, chunkPart, bLastChunk);
// Let's add any file-specific header.
beforeFile(0);
// Actual upload of the file:
this.filesToUpload[0].uploadFile(getOutputStream(), thisChunkSize);
// If we are not in chunk mode, or if it was the last chunk,
// upload should be finished.
if (bLastChunk && this.filesToUpload[0].getRemainingLength() > 0) {
throw new JUploadExceptionUploadFailed(
"Files has not be entirely uploaded. The remaining size is "
+ this.filesToUpload[0].getRemainingLength()
+ " bytes. File size was: "
+ this.filesToUpload[0].getUploadLength()
+ " bytes.");
}
// Let's add any file-specific header.
afterFile(0);
// Let's finish the request, and wait for the server Output, if
// any (not applicable in FTP)
int status = finishRequest();
// We now ask to the uploadPolicy, if it was a success.
// If not, the isUploadSuccessful should raise an exception.
this.uploadPolicy.checkUploadSuccess(status, getResponseMsg(),
getResponseBody());
cleanRequest();
}
// Let's free any locked resource
this.filesToUpload[0].afterUpload();
// Let's tell our manager that we've done the job!
this.fileUploadManagerThread
.anotherFileHasBeenSent(this.filesToUpload[0]);
}// doChunkedUpload
/**
* Execution of an upload, in standard mode. This method uploads all files
* in the {@link #filesToUpload} array.
*
* @throws JUploadException When any error occurs, or when there is more
* than one file in {@link #filesToUpload}.
*/
final private void doNonChunkedUpload(final long totalContentLength,
final long totalFileLength) throws JUploadException {
// First step is to prepare all files.
startRequest(totalContentLength, false, 0, true);
// Then, upload each file.
for (int i = 0; i < this.filesToUpload.length
&& !this.fileUploadManagerThread.isUploadStopped(); i++) {
// We are about to start a new upload.
this.fileUploadManagerThread.setUploadStatus(i,
FileUploadManagerThread.UPLOAD_STATUS_UPLOADING);
// Let's add any file-specific header.
beforeFile(i);
// Actual upload of the file:
this.filesToUpload[i].uploadFile(getOutputStream(),
this.filesToUpload[i].getUploadLength());
// Let's free any locked resource
this.filesToUpload[i].afterUpload();
// Let's add any file-specific header.
afterFile(i);
// Let's tell our manager that we've done the job!
// Ok, maybe the server will refuse it, but we won't say that now!
this.fileUploadManagerThread
.anotherFileHasBeenSent(this.filesToUpload[i]);
}
// We are finished with this one. Let's display it.
this.fileUploadManagerThread
.setUploadStatus(
this.filesToUpload.length,
FileUploadManagerThread.UPLOAD_STATUS_UPLOADED_WAITING_FOR_RESPONSE);
// Let's finish the request, and wait for the server Output, if
// any (not applicable in FTP)
int status = finishRequest();
// We now ask to the uploadPolicy, if it was a success.
// If not, the isUploadSuccessful should raise an exception.
this.uploadPolicy.checkUploadSuccess(status, getResponseMsg(),
getResponseBody());
cleanRequest();
}// doNonChunkedUpload
/** @see FileUploadThread#close() */
public void close() {
try {
cleanAll();
} catch (JUploadException e) {
this.uploadPolicy.displayErr(e);
}
}
/**
* Replace single \r and \n by uniform end of line characters (CRLF). This
* makes it easier, to search for string within the body.
*
* @param s The original string
* @return The string with single \r and \n modified changed to CRLF (\r\n).
*/
public final String normalizeCRLF(String s) {
Pattern p = Pattern.compile("\\r\\n|\\r|\\n", Pattern.MULTILINE);
String[] lines = p.split(s);
// Worst case: the s string contains only \n or \r characters: we then
// need to triple the string length. Let's say double is enough.
StringBuffer sb = new StringBuffer(s.length() * 2);
for (int i = 0; i < lines.length; i += 1) {
sb.append(lines[i]).append("\r\n");
}
return sb.toString();
}
/**
* Replace \r and \n by correctly displayed end of line characters. Used to
* display debug output. It also replace any single \r or \n by \r\n, to
* make it easier, to search for string within the body.
*
* @param s The original string
* @return The string with \r and \n modified, to be correctly displayed.
*/
public final String quoteCRLF(String s) {
return s.replaceAll("\r\n", "\\\\r\\\\n\n");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -