📄 multipartrequest.java
字号:
read = readLine(in, blockOfBytes);
strLine = (read > 0) ? new String(blockOfBytes, 0, read, charEncoding)
: null;
// Must be boundary at top of loop, otherwise we have finished.
if ((strLine == null) || (strLine.indexOf(this.strBoundary) == -1)) {
throw new IOException("Invalid Form Data, no boundary encountered.");
}
// At the top of loop, we assume that the Content-Disposition line is next, otherwise we are at the end.
while (true) {
// Get Content-Disposition line.
read = readLine(in, blockOfBytes);
if (read <= 0) {
break; // Nothing to do.
} else {
strLine = new String(blockOfBytes, 0, read, charEncoding);
// TODO: Improve performance by getting both the name and filename from strLine in one go...
strName = trimQuotes(getValue("name", strLine));
// If this is not null, it indicates that we are processing a filename.
// Now if not null, strip it of any directory information.
strFilename = trimQuotes(getValue("filename", strLine));
// No filename specified at all - parameter
if (strFilename == null) {
// Skip blank line.
readLine(in, blockOfBytes);
String param = readParameter(in);
addParameter(strName, param);
} else // (strFilename!=null)
{
// Fix: did not check whether filename was empty string indicating a FILE was not passed.
if (strFilename.length() == 0) {
// FIX 1.14: IE problem with empty filename.
read = readLine(in, blockOfBytes);
strLine = (read > 0)
? new String(blockOfBytes, 0, read, charEncoding)
: null;
// FIX 1.14 IE Problem still: Check for content-type and extra line, even though no file specified.
if ((strLine != null) &&
strLine.startsWith("Content-Type:")) {
readLine(in, blockOfBytes);
}
// Skip blank line.
readLine(in, blockOfBytes);
// Fix: FILE INPUT TYPE, but no file passed as input...
addFileParameter(strName,
new Object[] { null, null, null, null });
readLine(in, blockOfBytes);
} else // File uploaded, or at least a filename was specified, it could still be spurious.
{
// Need to get the content type.
read = readLine(in, blockOfBytes);
strLine = (read > 0)
? new String(blockOfBytes, 0, read, charEncoding)
: null;
strContentType = "application/octet-stream";
// Fix 1.11: If not null AND strLine.length() is long enough.
// Modified in 1.19, as we should be checking if it is actually a Content-Type.
//if (strLine!=null&&strLine.length()>"Content-Type: ".length())
if ((strLine != null) &&
strLine.startsWith("Content-Type:")) //Changed 1.19
{
strContentType = strLine.substring("Content-Type:".length())
.trim(); // Changed 1.13
// Skip blank line, but only if a Content-Type was specified.
readLine(in, blockOfBytes);
}
long filesize = -1;
// Will remain null for read onto file system uploads.
byte[] contentsOfFile = null;
// Get the BASENAME version of strFilename.
strFilename = getBasename(strFilename);
if (filePrefix != null) {
strFilename = filePrefix + strFilename;
}
// Are we loading files into memory instead of the filesystem?
if (loadIntoMemory) {
contentsOfFile = readFile(in);
if (contentsOfFile != null) {
filesize = contentsOfFile.length;
}
} else { // Read the file onto file system.
filesize = readAndWriteFile(in, strFilename);
}
// Fix 1.18 for multiple FILE parameter values.
if (filesize > 0) {
addFileParameter(strName,
new Object[] {
strFilename, strContentType,
new Long(filesize), contentsOfFile
});
} else { // Zero length file.
addFileParameter(strName,
new Object[] {
strFilename, null, new Long(0), null
});
}
}
}
}
}
// while
}
/**
So we can put the logic for supporting multiple parameters with the same
form field name in the one location.
*/
private void addParameter(String strName, String value) {
// Fix 1.16: for multiple parameter values.
Object objParms = htParameters.get(strName);
// Add an new entry to the param vector.
if (objParms instanceof Vector) {
((Vector) objParms).addElement(value);
} else if (objParms instanceof String) // There is only one entry, so we create a vector!
{
Vector vecParms = new Vector();
vecParms.addElement(objParms);
vecParms.addElement(value);
htParameters.put(strName, vecParms);
} else { // first entry for strName.
htParameters.put(strName, value);
}
}
/**
So we can put the logic for supporting multiple files with the same
form field name in the one location.
Assumes that this method will never be called with a null fileObj or strFilename.
*/
private void addFileParameter(String strName, Object[] fileObj) {
Object objParms = htFiles.get(strName);
// Add an new entry to the param vector.
if (objParms instanceof Vector) {
((Vector) objParms).addElement(fileObj);
} else if (objParms instanceof Object[]) // There is only one entry, so we create a vector!
{
Vector vecParms = new Vector();
vecParms.addElement(objParms);
vecParms.addElement(fileObj);
htFiles.put(strName, vecParms);
} else { // first entry for strName.
htFiles.put(strName, fileObj);
}
}
/**
Read parameters, assume already passed Content-Disposition and blank line.
@return the value read in.
*/
private String readParameter(InputStream in) throws IOException {
StringBuffer buf = new StringBuffer();
int read = -1;
String line = null;
while (true) {
read = readLine(in, blockOfBytes);
if (read < 0) {
throw new IOException("Stream ended prematurely.");
}
// Change v1.18: Only instantiate string once for performance reasons.
line = new String(blockOfBytes, 0, read, charEncoding);
if ((read < blockOfBytes.length) &&
(line.indexOf(this.strBoundary) != -1)) {
break; // Boundary found, we need to finish up.
} else {
buf.append(line);
}
}
if (buf.length() > 0) {
buf.setLength(getLengthMinusEnding(buf));
}
return buf.toString();
}
/**
Read from in, write to out, minus last two line ending bytes.
*/
private long readAndWrite(InputStream in, OutputStream out)
throws IOException {
long fileSize = 0;
int read = -1;
// This variable will be assigned the bytes actually read.
byte[] secondLineOfBytes = new byte[blockOfBytes.length];
// So we do not have to keep creating the second array.
int sizeOfSecondArray = 0;
while (true) {
read = readLine(in, blockOfBytes);
if (read < 0) {
throw new IOException("Stream ended prematurely.");
}
// Found boundary.
if ((read < blockOfBytes.length) &&
(new String(blockOfBytes, 0, read, charEncoding).indexOf(
this.strBoundary) != -1)) {
// Write the line, minus any line ending bytes.
//The secondLineOfBytes will NEVER BE NON-NULL if out==null, so there is no need to included this in the test
if (sizeOfSecondArray != 0) {
// Only used once, so declare here.
int actualLength = getLengthMinusEnding(secondLineOfBytes,
sizeOfSecondArray);
if ((actualLength > 0) && (out != null)) {
out.write(secondLineOfBytes, 0, actualLength);
// Update file size.
fileSize += actualLength;
}
}
break;
} else {
// Write out previous line.
//The sizeOfSecondArray will NEVER BE ZERO if out==null, so there is no need to included this in the test
if (sizeOfSecondArray != 0) {
out.write(secondLineOfBytes, 0, sizeOfSecondArray);
// Update file size.
fileSize += sizeOfSecondArray;
}
// out will always be null, so there is no need to reset sizeOfSecondArray to zero each time.
if (out != null) {
//Copy the read bytes into the array.
System.arraycopy(blockOfBytes, 0, secondLineOfBytes, 0, read);
// That is how many bytes to read from the secondLineOfBytes
sizeOfSecondArray = read;
}
}
}
//Return the number of bytes written to outstream.
return fileSize;
}
/**
Read a Multipart section that is a file type. Assumes that the Content-Disposition/Content-Type and blank line
have already been processed. So we read until we hit a boundary, then close file and return.
@exception IOException if an error occurs writing the file.
@return the number of bytes read.
*/
private long readAndWriteFile(InputStream in, String strFilename)
throws IOException {
// Store a reference to this, as we may need to delete it later.
File outFile = new File(fileOutPutDirectory, strFilename);
BufferedOutputStream out = null;
// Do not bother opening a OutputStream, if we cannot even write the file.
if (fileOutPutDirectory != null) {
out = new BufferedOutputStream(new FileOutputStream(outFile));
}
long count = readAndWrite(in, out);
// Count would NOT be larger than zero if out was null.
if (count > 0) {
out.flush();
out.close();
} else {
out.close();
// Delete file as empty. We should be able to delete it, if we can open it!
outFile.delete();
}
return count;
}
/**
* If the fileOutPutDirectory wasn't specified, just read the file to memory.
*
* @param strName - Url parameter this file was loaded under.
* @return contents of file, from which you can garner the size as well.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -