HTTP Post请求的四种编码方式
文章目录
HttpData
HttpDataFactory
DefaultHttpDataFactory
属性
构造方法
getList(HttpRequest)
[createAttribute(HttpRequest, String name)](#createAttribute(HttpRequest, String name))
[createAttribute(HttpRequest request, String name, long definedSize)](#createAttribute(HttpRequest request, String name, long definedSize))
[createAttribute(HttpRequest request, String name, String value)](#createAttribute(HttpRequest request, String name, String value))
createFileUpload
removeHttpDataFromClean
cleanRequestHttpData
cleanAllHttpData
HttpData
HttpData
HttpDataFactory
java
复制代码
public interface HttpDataFactory {
void setMaxLimit(long max);
Attribute createAttribute(HttpRequest request, String name);
Attribute createAttribute(HttpRequest request, String name, long definedSize);
Attribute createAttribute(HttpRequest request, String name, String value);
FileUpload createFileUpload(HttpRequest request,
String name,
String filename,
String contentType,
String contentTransferEncoding, Charset charset,
long size);
void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data);
void cleanRequestHttpData(HttpRequest request);
void cleanAllHttpData();
}
DefaultHttpDataFactory
属性
java
复制代码
// 16 KB
public static final long MINSIZE = 0x4000;
public static final long MAXSIZE = -1;
final boolean useDisk;
final boolean checkSize;
long minSize;
long maxSize = -1;
Charset charset = HttpConstants.DEFAULT_CHARSET;
String baseDir;
boolean deleteOnExit;
final Map<HttpRequest, List<HttpData>> requestFileDeleteMap =
Collections.synchronizedMap(new IdentityHashMap<HttpRequest, List<HttpData>>());
构造方法
java
复制代码
//
public DefaultHttpDataFactory() {
useDisk = false;
checkSize = true;
// 默认16kB
minSize = MINSIZE;
}
public DefaultHttpDataFactory(Charset charset) {
this();
this.charset = charset;
}
public DefaultHttpDataFactory(boolean useDisk) {
this.useDisk = useDisk;
checkSize = false;
}
public DefaultHttpDataFactory(boolean useDisk, Charset charset) {
this(useDisk);
this.charset = charset;
}
public DefaultHttpDataFactory(long minSize) {
useDisk = false;
checkSize = true;
this.minSize = minSize;
}
public DefaultHttpDataFactory(long minSize, Charset charset) {
this(minSize);
this.charset = charset;
}
getList(HttpRequest)
java
复制代码
private List<HttpData> getList(HttpRequest request) {
// 从 requestFileDeleteMap 中,获取指定 request对应的 HttpData 集合
List<HttpData> list = requestFileDeleteMap.get(request);
// 如果没有获取到,则初始化该 HttpData 集合
if (list == null) {
list = new ArrayList<HttpData>();
requestFileDeleteMap.put(request, list);
}
// 返回 HttpData 集合
return list;
}
createAttribute(HttpRequest, String name)
java
复制代码
@Override
public Attribute createAttribute(HttpRequest request, String name) {
// 若useDisk为true
if (useDisk) {
// 创建的是 DiskAttribute
Attribute attribute = new DiskAttribute(name, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
// 将创建的 DiskAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
// 此时 useDisk为false
// 若checkSize为true
if (checkSize) {
// 创建的是 MixedAttribute
Attribute attribute = new MixedAttribute(name, minSize, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
// 将创建的 MixedAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
// 此时 checkSize为false
// 创建的是 MemoryAttribute
MemoryAttribute attribute = new MemoryAttribute(name);
attribute.setMaxSize(maxSize);
return attribute;
}
createAttribute(HttpRequest request, String name, long definedSize)
java
复制代码
@Override
public Attribute createAttribute(HttpRequest request, String name, long definedSize) {
// 若useDisk为true
if (useDisk) {
// 创建的是 DiskAttribute
Attribute attribute = new DiskAttribute(name, definedSize, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
// 将创建的 DiskAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
// 此时 useDisk为false
// 若checkSize为true
if (checkSize) {
// 创建的是 MixedAttribute
Attribute attribute = new MixedAttribute(name, definedSize, minSize, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
// 将创建的 MixedAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
// 此时 checkSize为false
// 创建的是 MemoryAttribute
MemoryAttribute attribute = new MemoryAttribute(name, definedSize);
attribute.setMaxSize(maxSize);
return attribute;
}
createAttribute(HttpRequest request, String name, String value)
java
复制代码
@Override
public Attribute createAttribute(HttpRequest request, String name, String value) {
// 若useDisk为true
if (useDisk) {
Attribute attribute;
try {
// 创建的是 DiskAttribute
attribute = new DiskAttribute(name, value, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
} catch (IOException e) {
// 发生异常, 则创建 MixedAttribute
attribute = new MixedAttribute(name, value, minSize, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
}
// 检查data.length() 与 maxSize 大小
checkHttpDataSize(attribute);
// 将创建的 MixedAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
// 若checkSize为true
if (checkSize) {
// 创建的是 MixedAttribute
Attribute attribute = new MixedAttribute(name, value, minSize, charset, baseDir, deleteOnExit);
attribute.setMaxSize(maxSize);
// 检查data.length() 与 maxSize 大小
checkHttpDataSize(attribute);
// 将创建的 MixedAttribute对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(attribute);
return attribute;
}
try {
// 此时 checkSize为false
// 创建的是 MemoryAttribute
MemoryAttribute attribute = new MemoryAttribute(name, value, charset);
attribute.setMaxSize(maxSize);
// 检查data.length() 与 maxSize 大小
checkHttpDataSize(attribute);
return attribute;
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
checkHttpDataSize(HttpData)
java
复制代码
private static void checkHttpDataSize(HttpData data) {
try {
// 检查data.length() 与 maxSize 大小, 如果超过maxSize, 则抛出异常
data.checkSize(data.length());
} catch (IOException ignored) {
throw new IllegalArgumentException("Attribute bigger than maxSize allowed");
}
}
createFileUpload
java
复制代码
@Override
public FileUpload createFileUpload(HttpRequest request,
String name,
String filename,
String contentType,
String contentTransferEncoding,
Charset charset,
long size) {
// 若useDisk为true
if (useDisk) {
// 创建FileUpload对象
FileUpload fileUpload = new DiskFileUpload(name,
filename,
contentType,
contentTransferEncoding,
charset,
size,
baseDir,
deleteOnExit);
fileUpload.setMaxSize(maxSize);
// 检查fileUpload.length() 与 maxSize 大小
checkHttpDataSize(fileUpload);
// 将创建的 fileUpload对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(fileUpload);
return fileUpload;
}
// 若checkSize为true
if (checkSize) {
// 创建 MixedFileUpload对象
FileUpload fileUpload = new MixedFileUpload(name,
filename,
contentType,
contentTransferEncoding,
charset,
size,
minSize,
baseDir,
deleteOnExit);
fileUpload.setMaxSize(maxSize);
// 检查fileUpload.length() 与 maxSize 大小
checkHttpDataSize(fileUpload);
// 将创建的 fileUpload对象 放入 requestFileDeleteMap 中
List<HttpData> list = getList(request);
list.add(fileUpload);
return fileUpload;
}
// 此时 checkSize为false
// 创建的是 MemoryFileUpload
MemoryFileUpload fileUpload = new MemoryFileUpload(name,
filename,
contentType,
contentTransferEncoding,
charset,
size);
fileUpload.setMaxSize(maxSize);
// 检查data.length() 与 maxSize 大小
checkHttpDataSize(fileUpload);
return fileUpload;
}
removeHttpDataFromClean
java
复制代码
@Override
public void removeHttpDataFromClean(HttpRequest request, InterfaceHttpData data) {
// data 必须是 InterfaceHttpData 类型
if (!(data instanceof HttpData)) {
return;
}
// 获取request对应的 HttpData 集合, 如果该集合为null, 直接返回
List<HttpData> list = requestFileDeleteMap.get(request);
if (list == null) {
return;
}
// 从 HttpData 集合中,使用迭代器的方式 移除 data
Iterator<HttpData> i = list.iterator();
while (i.hasNext()) {
HttpData n = i.next();
if (n == data) {
i.remove();
if (list.isEmpty()) {
requestFileDeleteMap.remove(request);
}
return;
}
}
}
cleanRequestHttpData
java
复制代码
@Override
public void cleanRequestHttpData(HttpRequest request) {
// 获取request对应的 HttpData 集合
List<HttpData> list = requestFileDeleteMap.remove(request);
// 如果 HttpData 集合 不为null, 则遍历该 HttpData 集合, 并逐个释放 HttpData
if (list != null) {
for (HttpData data : list) {
data.release();
}
}
}
cleanAllHttpData
java
复制代码
@Override
public void cleanAllHttpData() {
// 获取 requestFileDeleteMap 的迭代器
Iterator<Entry<HttpRequest, List<HttpData>>> i = requestFileDeleteMap.entrySet().iterator();
// 遍历
while (i.hasNext()) {
// 获取当前遍历的 entry
Entry<HttpRequest, List<HttpData>> e = i.next();
// 逐个释放 HttpData
List<HttpData> list = e.getValue();
for (HttpData data : list) {
data.release();
}
// 从 requestFileDeleteMap 中移除 entry
i.remove();
}
}
HttpData
java
复制代码
public interface HttpData extends InterfaceHttpData, ByteBufHolder {
long getMaxSize();
void setMaxSize(long maxSize);
void checkSize(long newSize) throws IOException;
void setContent(ByteBuf buffer) throws IOException;
void addContent(ByteBuf buffer, boolean last) throws IOException;
void setContent(File file) throws IOException;
void setContent(InputStream inputStream) throws IOException;
boolean isCompleted();
long length();
long definedLength();
void delete();
byte[] get() throws IOException;
ByteBuf getByteBuf() throws IOException;
ByteBuf getChunk(int length) throws IOException;
String getString() throws IOException;
String getString(Charset encoding) throws IOException;
void setCharset(Charset charset);
Charset getCharset();
boolean renameTo(File dest) throws IOException;
boolean isInMemory();
File getFile() throws IOException;
@Override
HttpData copy();
@Override
HttpData duplicate();
@Override
HttpData retainedDuplicate();
@Override
HttpData replace(ByteBuf content);
@Override
HttpData retain();
@Override
HttpData retain(int increment);
@Override
HttpData touch();
@Override
HttpData touch(Object hint);
}
AbstractHttpData
java
复制代码
public abstract class AbstractHttpData extends AbstractReferenceCounted
implements HttpData {
private static final Pattern STRIP_PATTERN = Pattern.compile("(?:^\\s+|\\s+$|\\n)");
private static final Pattern REPLACE_PATTERN = Pattern.compile("[\\r\\t]");
private final String name;
protected long definedSize;
protected long size;
private Charset charset = HttpConstants.DEFAULT_CHARSET;
private boolean completed;
private long maxSize = DefaultHttpDataFactory.MAXSIZE;
protected AbstractHttpData(String name, Charset charset, long size) {
ObjectUtil.checkNotNull(name, "name");
name = REPLACE_PATTERN.matcher(name).replaceAll(" ");
name = STRIP_PATTERN.matcher(name).replaceAll("");
this.name = checkNonEmpty(name, "name");
if (charset != null) {
setCharset(charset);
}
definedSize = size;
}
@Override
public long getMaxSize() {
return maxSize;
}
@Override
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
}
@Override
public void checkSize(long newSize) throws IOException {
if (maxSize >= 0 && newSize > maxSize) {
throw new IOException("Size exceed allowed maximum capacity");
}
}
@Override
public String getName() {
return name;
}
@Override
public boolean isCompleted() {
return completed;
}
protected void setCompleted() {
completed = true;
}
@Override
public Charset getCharset() {
return charset;
}
@Override
public void setCharset(Charset charset) {
this.charset = ObjectUtil.checkNotNull(charset, "charset");
}
@Override
public long length() {
return size;
}
@Override
public long definedLength() {
return definedSize;
}
@Override
public ByteBuf content() {
try {
return getByteBuf();
} catch (IOException e) {
throw new ChannelException(e);
}
}
@Override
protected void deallocate() {
delete();
}
@Override
public HttpData retain() {
super.retain();
return this;
}
@Override
public HttpData retain(int increment) {
super.retain(increment);
return this;
}
@Override
public abstract HttpData touch();
@Override
public abstract HttpData touch(Object hint);
}
AbstractDiskHttpData
java
复制代码
public abstract class AbstractDiskHttpData extends AbstractHttpData {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractDiskHttpData.class);
private File file;
private boolean isRenamed;
private FileChannel fileChannel;
protected AbstractDiskHttpData(String name, Charset charset, long size) {
super(name, charset, size);
}
/**
*
* @return the real DiskFilename (basename)
*/
protected abstract String getDiskFilename();
/**
*
* @return the default prefix
*/
protected abstract String getPrefix();
/**
*
* @return the default base Directory
*/
protected abstract String getBaseDirectory();
/**
*
* @return the default postfix
*/
protected abstract String getPostfix();
/**
*
* @return True if the file should be deleted on Exit by default
*/
protected abstract boolean deleteOnExit();
/**
* @return a new Temp File from getDiskFilename(), default prefix, postfix and baseDirectory
*/
private File tempFile() throws IOException {
String newpostfix;
String diskFilename = getDiskFilename();
if (diskFilename != null) {
newpostfix = '_' + diskFilename;
} else {
newpostfix = getPostfix();
}
File tmpFile;
if (getBaseDirectory() == null) {
// create a temporary file
tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, null);
} else {
tmpFile = PlatformDependent.createTempFile(getPrefix(), newpostfix, new File(
getBaseDirectory()));
}
if (deleteOnExit()) {
// See https://github.com/netty/netty/issues/10351
DeleteFileOnExitHook.add(tmpFile.getPath());
}
return tmpFile;
}
@Override
public void setContent(ByteBuf buffer) throws IOException {
ObjectUtil.checkNotNull(buffer, "buffer");
try {
size = buffer.readableBytes();
checkSize(size);
if (definedSize > 0 && definedSize < size) {
throw new IOException("Out of size: " + size + " > " + definedSize);
}
if (file == null) {
file = tempFile();
}
if (buffer.readableBytes() == 0) {
// empty file
if (!file.createNewFile()) {
if (file.length() == 0) {
return;
} else {
if (!file.delete() || !file.createNewFile()) {
throw new IOException("file exists already: " + file);
}
}
}
return;
}
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
try {
accessFile.setLength(0);
FileChannel localfileChannel = accessFile.getChannel();
ByteBuffer byteBuffer = buffer.nioBuffer();
int written = 0;
while (written < size) {
written += localfileChannel.write(byteBuffer);
}
buffer.readerIndex(buffer.readerIndex() + written);
localfileChannel.force(false);
} finally {
accessFile.close();
}
setCompleted();
} 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();
}
}
@Override
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);
}
if (file == null) {
file = tempFile();
}
if (fileChannel == null) {
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
fileChannel = accessFile.getChannel();
}
int remaining = localsize;
long position = fileChannel.position();
int index = buffer.readerIndex();
while (remaining > 0) {
int written = buffer.getBytes(index, fileChannel, position, remaining);
if (written < 0) {
break;
}
remaining -= written;
position += written;
index += written;
}
fileChannel.position(position);
buffer.readerIndex(index);
size += localsize - remaining;
} 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) {
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
fileChannel = accessFile.getChannel();
}
try {
fileChannel.force(false);
} finally {
fileChannel.close();
}
fileChannel = null;
setCompleted();
} else {
ObjectUtil.checkNotNull(buffer, "buffer");
}
}
@Override
public void setContent(File file) throws IOException {
long size = file.length();
checkSize(size);
this.size = size;
if (this.file != null) {
delete();
}
this.file = file;
isRenamed = true;
setCompleted();
}
@Override
public void setContent(InputStream inputStream) throws IOException {
ObjectUtil.checkNotNull(inputStream, "inputStream");
if (file != null) {
delete();
}
file = tempFile();
RandomAccessFile accessFile = new RandomAccessFile(file, "rw");
int written = 0;
try {
accessFile.setLength(0);
FileChannel localfileChannel = accessFile.getChannel();
byte[] bytes = new byte[4096 * 4];
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
int read = inputStream.read(bytes);
while (read > 0) {
byteBuffer.position(read).flip();
written += localfileChannel.write(byteBuffer);
checkSize(written);
read = inputStream.read(bytes);
}
localfileChannel.force(false);
} finally {
accessFile.close();
}
size = written;
if (definedSize > 0 && definedSize < size) {
if (!file.delete()) {
logger.warn("Failed to delete: {}", file);
}
file = null;
throw new IOException("Out of size: " + size + " > " + definedSize);
}
isRenamed = true;
setCompleted();
}
@Override
public void delete() {
if (fileChannel != null) {
try {
fileChannel.force(false);
} catch (IOException e) {
logger.warn("Failed to force.", e);
} finally {
try {
fileChannel.close();
} catch (IOException e) {
logger.warn("Failed to close a file.", e);
}
}
fileChannel = null;
}
if (!isRenamed) {
String filePath = null;
if (file != null && file.exists()) {
filePath = file.getPath();
if (!file.delete()) {
filePath = null;
logger.warn("Failed to delete: {}", file);
}
}
// If you turn on deleteOnExit make sure it is executed.
if (deleteOnExit() && filePath != null) {
DeleteFileOnExitHook.remove(filePath);
}
file = null;
}
}
@Override
public byte[] get() throws IOException {
if (file == null) {
return EmptyArrays.EMPTY_BYTES;
}
return readFrom(file);
}
@Override
public ByteBuf getByteBuf() throws IOException {
if (file == null) {
return EMPTY_BUFFER;
}
byte[] array = readFrom(file);
return wrappedBuffer(array);
}
@Override
public ByteBuf getChunk(int length) throws IOException {
if (file == null || length == 0) {
return EMPTY_BUFFER;
}
if (fileChannel == null) {
RandomAccessFile accessFile = new RandomAccessFile(file, "r");
fileChannel = accessFile.getChannel();
}
int read = 0;
ByteBuffer byteBuffer = ByteBuffer.allocate(length);
try {
while (read < length) {
int readnow = fileChannel.read(byteBuffer);
if (readnow == -1) {
fileChannel.close();
fileChannel = null;
break;
}
read += readnow;
}
} catch (IOException e) {
fileChannel.close();
fileChannel = null;
throw e;
}
if (read == 0) {
return EMPTY_BUFFER;
}
byteBuffer.flip();
ByteBuf buffer = wrappedBuffer(byteBuffer);
buffer.readerIndex(0);
buffer.writerIndex(read);
return buffer;
}
@Override
public String getString() throws IOException {
return getString(HttpConstants.DEFAULT_CHARSET);
}
@Override
public String getString(Charset encoding) throws IOException {
if (file == null) {
return "";
}
if (encoding == null) {
byte[] array = readFrom(file);
return new String(array, HttpConstants.DEFAULT_CHARSET.name());
}
byte[] array = readFrom(file);
return new String(array, encoding.name());
}
@Override
public boolean isInMemory() {
return false;
}
@Override
public boolean renameTo(File dest) throws IOException {
ObjectUtil.checkNotNull(dest, "dest");
if (file == null) {
throw new IOException("No file defined so cannot be renamed");
}
if (!file.renameTo(dest)) {
// must copy
IOException exception = null;
RandomAccessFile inputAccessFile = null;
RandomAccessFile outputAccessFile = null;
long chunkSize = 8196;
long position = 0;
try {
inputAccessFile = new RandomAccessFile(file, "r");
outputAccessFile = new RandomAccessFile(dest, "rw");
FileChannel in = inputAccessFile.getChannel();
FileChannel out = outputAccessFile.getChannel();
while (position < size) {
if (chunkSize < size - position) {
chunkSize = size - position;
}
position += in.transferTo(position, chunkSize, out);
}
} catch (IOException e) {
exception = e;
} finally {
if (inputAccessFile != null) {
try {
inputAccessFile.close();
} catch (IOException e) {
if (exception == null) { // Choose to report the first exception
exception = e;
} else {
logger.warn("Multiple exceptions detected, the following will be suppressed {}", e);
}
}
}
if (outputAccessFile != null) {
try {
outputAccessFile.close();
} catch (IOException e) {
if (exception == null) { // Choose to report the first exception
exception = e;
} else {
logger.warn("Multiple exceptions detected, the following will be suppressed {}", e);
}
}
}
}
if (exception != null) {
throw exception;
}
if (position == size) {
if (!file.delete()) {
logger.warn("Failed to delete: {}", file);
}
file = dest;
isRenamed = true;
return true;
} else {
if (!dest.delete()) {
logger.warn("Failed to delete: {}", dest);
}
return false;
}
}
file = dest;
isRenamed = true;
return true;
}
/**
* Utility function
*
* @return the array of bytes
*/
private static byte[] readFrom(File src) throws IOException {
long srcsize = src.length();
if (srcsize > Integer.MAX_VALUE) {
throw new IllegalArgumentException(
"File too big to be loaded in memory");
}
RandomAccessFile accessFile = new RandomAccessFile(src, "r");
byte[] array = new byte[(int) srcsize];
try {
FileChannel fileChannel = accessFile.getChannel();
ByteBuffer byteBuffer = ByteBuffer.wrap(array);
int read = 0;
while (read < srcsize) {
read += fileChannel.read(byteBuffer);
}
} finally {
accessFile.close();
}
return array;
}
@Override
public File getFile() throws IOException {
return file;
}
@Override
public HttpData touch() {
return this;
}
@Override
public HttpData touch(Object hint) {
return this;
}
}
AbstractMemoryHttpData
java
复制代码
public abstract class AbstractMemoryHttpData extends AbstractHttpData {
private ByteBuf byteBuf;
private int chunkPosition;
protected AbstractMemoryHttpData(String name, Charset charset, long size) {
super(name, charset, size);
byteBuf = EMPTY_BUFFER;
}
@Override
public void setContent(ByteBuf buffer) throws IOException {
ObjectUtil.checkNotNull(buffer, "buffer");
long localsize = buffer.readableBytes();
try {
checkSize(localsize);
} catch (IOException e) {
buffer.release();
throw e;
}
if (definedSize > 0 && definedSize < localsize) {
buffer.release();
throw new IOException("Out of size: " + localsize + " > " +
definedSize);
}
if (byteBuf != null) {
byteBuf.release();
}
byteBuf = buffer;
size = localsize;
setCompleted();
}
@Override
public void setContent(InputStream inputStream) throws IOException {
ObjectUtil.checkNotNull(inputStream, "inputStream");
byte[] bytes = new byte[4096 * 4];
ByteBuf buffer = buffer();
int written = 0;
try {
int read = inputStream.read(bytes);
while (read > 0) {
buffer.writeBytes(bytes, 0, read);
written += read;
checkSize(written);
read = inputStream.read(bytes);
}
} catch (IOException e) {
buffer.release();
throw e;
}
size = written;
if (definedSize > 0 && definedSize < size) {
buffer.release();
throw new IOException("Out of size: " + size + " > " + definedSize);
}
if (byteBuf != null) {
byteBuf.release();
}
byteBuf = buffer;
setCompleted();
}
@Override
public void addContent(ByteBuf buffer, boolean last)
throws IOException {
if (buffer != null) {
long localsize = buffer.readableBytes();
try {
checkSize(size + localsize);
} catch (IOException e) {
buffer.release();
throw e;
}
if (definedSize > 0 && definedSize < size + localsize) {
buffer.release();
throw new IOException("Out of size: " + (size + localsize) +
" > " + definedSize);
}
size += localsize;
if (byteBuf == null) {
byteBuf = buffer;
} else if (localsize == 0) {
// Nothing to add and byteBuf already exists
buffer.release();
} else if (byteBuf.readableBytes() == 0) {
// Previous buffer is empty, so just replace it
byteBuf.release();
byteBuf = buffer;
} else if (byteBuf instanceof CompositeByteBuf) {
CompositeByteBuf cbb = (CompositeByteBuf) byteBuf;
cbb.addComponent(true, buffer);
} else {
CompositeByteBuf cbb = compositeBuffer(Integer.MAX_VALUE);
cbb.addComponents(true, byteBuf, buffer);
byteBuf = cbb;
}
}
if (last) {
setCompleted();
} else {
ObjectUtil.checkNotNull(buffer, "buffer");
}
}
@Override
public void setContent(File file) throws IOException {
ObjectUtil.checkNotNull(file, "file");
long newsize = file.length();
if (newsize > Integer.MAX_VALUE) {
throw new IllegalArgumentException("File too big to be loaded in memory");
}
checkSize(newsize);
RandomAccessFile accessFile = new RandomAccessFile(file, "r");
ByteBuffer byteBuffer;
try {
FileChannel fileChannel = accessFile.getChannel();
try {
byte[] array = new byte[(int) newsize];
byteBuffer = ByteBuffer.wrap(array);
int read = 0;
while (read < newsize) {
read += fileChannel.read(byteBuffer);
}
} finally {
fileChannel.close();
}
} finally {
accessFile.close();
}
byteBuffer.flip();
if (byteBuf != null) {
byteBuf.release();
}
byteBuf = wrappedBuffer(Integer.MAX_VALUE, byteBuffer);
size = newsize;
setCompleted();
}
@Override
public void delete() {
if (byteBuf != null) {
byteBuf.release();
byteBuf = null;
}
}
@Override
public byte[] get() {
if (byteBuf == null) {
return EMPTY_BUFFER.array();
}
byte[] array = new byte[byteBuf.readableBytes()];
byteBuf.getBytes(byteBuf.readerIndex(), array);
return array;
}
@Override
public String getString() {
return getString(HttpConstants.DEFAULT_CHARSET);
}
@Override
public String getString(Charset encoding) {
if (byteBuf == null) {
return "";
}
if (encoding == null) {
encoding = HttpConstants.DEFAULT_CHARSET;
}
return byteBuf.toString(encoding);
}
/**
* Utility to go from a In Memory FileUpload
* to a Disk (or another implementation) FileUpload
* @return the attached ByteBuf containing the actual bytes
*/
@Override
public ByteBuf getByteBuf() {
return byteBuf;
}
@Override
public ByteBuf getChunk(int length) throws IOException {
if (byteBuf == null || length == 0 || byteBuf.readableBytes() == 0) {
chunkPosition = 0;
return EMPTY_BUFFER;
}
int sizeLeft = byteBuf.readableBytes() - chunkPosition;
if (sizeLeft == 0) {
chunkPosition = 0;
return EMPTY_BUFFER;
}
int sliceLength = length;
if (sizeLeft < length) {
sliceLength = sizeLeft;
}
ByteBuf chunk = byteBuf.retainedSlice(chunkPosition, sliceLength);
chunkPosition += sliceLength;
return chunk;
}
@Override
public boolean isInMemory() {
return true;
}
@Override
public boolean renameTo(File dest) throws IOException {
ObjectUtil.checkNotNull(dest, "dest");
if (byteBuf == null) {
// empty file
if (!dest.createNewFile()) {
throw new IOException("file exists already: " + dest);
}
return true;
}
int length = byteBuf.readableBytes();
long written = 0;
RandomAccessFile accessFile = new RandomAccessFile(dest, "rw");
try {
FileChannel fileChannel = accessFile.getChannel();
try {
if (byteBuf.nioBufferCount() == 1) {
ByteBuffer byteBuffer = byteBuf.nioBuffer();
while (written < length) {
written += fileChannel.write(byteBuffer);
}
} else {
ByteBuffer[] byteBuffers = byteBuf.nioBuffers();
while (written < length) {
written += fileChannel.write(byteBuffers);
}
}
fileChannel.force(false);
} finally {
fileChannel.close();
}
} finally {
accessFile.close();
}
return written == length;
}
@Override
public File getFile() throws IOException {
throw new IOException("Not represented by a file");
}
@Override
public HttpData touch() {
return touch(null);
}
@Override
public HttpData touch(Object hint) {
if (byteBuf != null) {
byteBuf.touch(hint);
}
return this;
}
}