HttpPostMultipartRequestExDecoder.getFileUpload
if(size == 0 && requestContentLength > CustomDiskFileUpload.DISK_FILE_THRESHOLD) {
LOGGER.info("request content length:{}, size:{}, use disk file", requestContentLength, size);
currentFileUpload = factory.createDiskFileUpload(request,
cleanString(nameAttribute.getValue()), cleanString(filenameAttribute.getValue()),
contentType, mechanism.value(), localCharset,
size);
}
CustomHttpDataFactory
public FileUpload createDiskFileUpload(HttpRequest request, String name, String filename,
String contentType, String contentTransferEncoding, Charset charset,
long size) {
FileUpload fileUpload = new CustomDiskFileUpload(name, filename, contentType,
contentTransferEncoding, charset, size);
fileUpload.setMaxSize(maxSize);
checkHttpDataSize(fileUpload);
List<HttpData> fileToDelete = getList(request);
fileToDelete.add(fileUpload);
return fileUpload;
}
HttpPostMultipartRequestExDecoder getFileUpload
if (!loadDataMultipart(undecodedChunk, delimiter, currentFileUpload)) {
// Delimiter is not found. Need more chunks.
return null;
}
HttpPostMultipartRequestExDecoder loadDataMultipart
private static boolean loadDataMultipart(ByteBuf undecodedChunk, String delimiter, HttpData httpData) {
if (!undecodedChunk.hasArray()) {
return loadDataMultipartStandard(undecodedChunk, delimiter, httpData);
}
HttpPostMultipartRequestExDecoder
1.遍历一遍 是否是分隔符–CgHnWodRCoGzI1yH0FKcfd_7KlyPpaWfOv末尾
2.httpData.addContent(content, delimiterFound);
3.重置读index
private static boolean loadDataMultipartStandard(ByteBuf undecodedChunk, String delimiter, HttpData httpData) {
int pageSize = DEFAULT_PAGE_SIZE;
final int startReaderIndex = undecodedChunk.readerIndex();
final int delimeterLength = delimiter.length();
int index = 0;
int lastPosition = startReaderIndex;
byte prevByte = HttpConstants.LF;
boolean delimiterFound = false;
boolean finish = false;
byte[] bytes = new byte[pageSize];
int len = 0,startIndex = 0;
while (undecodedChunk.isReadable()) {
if(httpData instanceof FileUpload){
if(finish){
break;
}
try {
len = Math.min(pageSize, undecodedChunk.readableBytes());
startIndex = undecodedChunk.readerIndex();
undecodedChunk.readBytes(bytes, 0, len);
undecodedChunk.readerIndex(startIndex + len);
for (int i = 0; i < len; i++) {
final byte nextByte = bytes[i];
// Check the delimiter
if (prevByte == HttpConstants.LF && nextByte == delimiter.codePointAt(index)) {
index++;
if (delimeterLength == index) {
delimiterFound = true;
finish = true;
break;
}
continue;
}
lastPosition = startIndex + i + 1;
if (nextByte == HttpConstants.LF) {
index = 0;
lastPosition -= (prevByte == HttpConstants.CR) ? 2 : 1;
}
prevByte = nextByte;
}
}catch(Exception e){
throw e;
}
}else {
final byte nextByte = undecodedChunk.readByte();
// Check the delimiter
if (prevByte == HttpConstants.LF && nextByte == delimiter.codePointAt(index)) {
index++;
if (delimeterLength == index) {
delimiterFound = true;
break;
}
continue;
}
lastPosition = undecodedChunk.readerIndex();
if (nextByte == HttpConstants.LF) {
index = 0;
lastPosition -= (prevByte == HttpConstants.CR) ? 2 : 1;
}
prevByte = nextByte;
}
}
if (prevByte == HttpConstants.CR) {
lastPosition--;
}
ByteBuf content = undecodedChunk.retainedSlice(startReaderIndex, lastPosition - startReaderIndex);
try {
httpData.addContent(content, delimiterFound);
} catch (IOException e) {
throw new ErrorDataDecoderException(e);
}
undecodedChunk.readerIndex(lastPosition);
return delimiterFound;
}
CustomDiskFileUpload.addContent
public void addContent(ByteBuf buffer, boolean last)
throws IOException {
if (buffer != null) {
try {
int localsize = buffer.readableBytes();
checkSize(size + localsize);
if (definedSize > 0 && definedSize < size + localsize) {
throw new IOException("Out of size: " + (size + localsize) +
" > " + definedSize);
}
ByteBuffer byteBuffer = null;
ByteBuffer[] byteBuffers = null;
if (buffer.nioBufferCount() == 1) {
byteBuffer = buffer.nioBuffer();
} else {
byteBuffers = buffer.nioBuffers();
}
int written = 0;
if (file == null) {
file = tempFile();
}
if (fileChannel == null) {
FileOutputStream outputStream = new FileOutputStream(file);
fileChannel = outputStream.getChannel();
}
int i = 0, len = byteBuffers != null ? byteBuffers.length : 0;
ByteBuffer buf;
while (written < localsize) {
if (byteBuffer != null) {
written += fileChannel.write(byteBuffer);
} else if (byteBuffers != null) {
written += fileChannel.write(byteBuffers);
}
}
size += localsize;
buffer.readerIndex(buffer.readerIndex() + written);
} finally {
// Release the buffer as it was retained before and we not need a reference to it at all
// See https://github.com/netty/netty/issues/1516
buffer.release();
}
}
if (last) {
if (file == null) {
file = tempFile();
}
if (fileChannel == null) {
FileOutputStream outputStream = new FileOutputStream(file);
fileChannel = outputStream.getChannel();
}
//fileChannel.force(false); //因为数据是临时存入ssd,所以不需要强制刷入磁盘
fileChannel.close();
fileChannel = null;
setCompleted();
} else {
if (buffer == null) {
throw new NullPointerException("buffer");
}
}
}