Netty中文件上传的实现
来源:互联网 发布:犀牛软件 垃圾袋 编辑:程序博客网 时间:2024/06/08 05:12
技术点描述
上传大文件并且没有内存压力的文件服务。
实现方案
Netty利用块(HttpChunk)对开发文件服务器端做了很好的实现:
内容存储方式:
内存、硬盘、混合存储。
参考源码包
- 源码包:
- 接口/抽象类/类说明:
- InterfaceHttpData(interface):实现该接口的对象可以用HttpPostRequestEncoder/Decoder编解码
- HttpDataFactory(interface):创建InterfaceHttpData对象
- HttpData(interface):继承InterfaceHttpData
- Attribute(interface):属性接口,继承HttpData
- FileUpLoad(interface):可存放在内存、临时文件或一些其他实现
DefaultHttpDataFactory
根据构造函数给FileUpload和Attribute提供默认的工厂。
- 重要方法:
- public DefaultHttpDataFactory(boolean useDisk) {
this.useDisk = useDisk;
checkSize = false;
}
参数为true时设置为硬盘存储,为false内存存储
- public DefaultHttpDataFactory(long minSize) {
useDisk = false;
checkSize = true;
this.minSize = minSize;
}
为混合存储模式,如果HttpData大于最小值将会存储在硬盘,否则存储在内存
- 重要属性
private final ConcurrentHashMap<HttpRequest, List<HttpData>> requestFileDeleteMap =
new ConcurrentHashMap<HttpRequest, List<HttpData>>();
保存所有HttpRequest的数据,直到调用cleanAllHttpDatas()
HttpPostRequestEncoder
说明:implements ChunkedInput(通过ChunkedWriteHandler传输)。将请求表单编码成POST。
主要方法:
HttpRequest finalizeRequest()
结束request头准备并返回将被发送的request.如果请求不需要分块,只有这一个请求被发送到服务端。
if (isMultipart) {
String value = HttpHeaders.Values.MULTIPART_FORM_DATA + "; " +
HttpHeaders.Values.BOUNDARY + "=" + multipartDataBoundary;
request.addHeader(HttpHeaders.Names.CONTENT_TYPE, value);
} else {
// Not multipart
request.addHeader(HttpHeaders.Names.CONTENT_TYPE,
HttpHeaders.Values.APPLICATION_X_WWW_FORM_URLENCODED);
}
判断需不需要上传文件并进行设置。
DiskFileUpload
将FileUpload存储到真实文件。
重要属性:
baseDirectory 存储上传文件的目录
deleteOnExitTemporaryFile 在虚拟机推出访问是是否删除文件,默认值为true
Demo实现
HttpUploadClient
bodyRequestEncoder.addBodyAttribute("getform", "POST");
bodyRequestEncoder.addBodyAttribute("info", "first value");
bodyRequestEncoder.addBodyAttribute("secondinfo", "secondvalue&");
bodyRequestEncoder.addBodyAttribute("thirdinfo", textAreaLong);
bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", true);//false 以二进制方式传输,true以文本方式传输
bodyRequestEncoder.addBodyAttribute("Send", "Send");
添加HttpPostRequestEncoder上传的属性和文件
HttpUploadServerHandler
DiskFileUpload.deleteOnExitTemporaryFile = false;
DiskFileUpload.baseDirectory = "D:\\"; DiskAttribute.deleteOnExitTemporaryFile = true; DiskAttribute.baseDirectory = "D:\\";
设置退出时是否删除临时生成的属性文件和上传的文件。
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
if (decoder != null) {
decoder.cleanFiles();
}
}
连接关闭时同时清除与此请求相关的文件。
if (fileUpload.isCompleted()) {
fileUpload.renameTo(File dest);//当上传结束时可以将文件写到指定目录,但不建议这样做。
}
以下是renameTo方法的实现
FileInputStream inputStream = new FileInputStream(file);
FileOutputStream outputStream = new FileOutputStream(dest);
FileChannel in = inputStream.getChannel();
FileChannel out = outputStream.getChannel();
int chunkSize = 8196;
long position = 0;
while (position < size) {
if (chunkSize < size - position) {
chunkSize = (int) (size - position);
}
position += in.transferTo(position, chunkSize , out);
}
在测试过程中发现这个方法很耗内存。
可以使用生成的临时文件,要清除requestFileDeleteMap中保存的数据。否则decoder.cleanFiles();会将临时文件删除
decoder.removeHttpDataFromClean(fileUpload);
- Netty中文件上传的实现
- struts2中文件上传的实现
- struts2中文件上传的实现
- PHP中文件上传功能的实现
- PHP中文件上传的功能模块实现
- webwork中文件上传实现
- webwork中文件上传实现
- 关于Easy UI中文件上传处理进度条的实现
- 关于Easy UI中文件上传处理进度条的实现
- struts中文件的上传
- javaWeb中文件的上传
- SWING中文件的上传
- Struts中文件的上传
- EasyJWeb中文件上传的处理
- 关于.net中文件上传的程序
- 关于Struts中文件的上传
- EasyJWeb中文件上传的处理
- EasyJWeb中文件上传的处理
- URAL 1732 Ministry of Truth KMP
- SPDY:Google开发的下一代HTTP协议
- Netty数据包大小的确定
- opencv 学习之 亮度检测
- Netty使用protobuf作为通信协议
- Netty中文件上传的实现
- Netty的超时机制
- primary同步数据到逻辑standby时报违反唯一约束(ora-00001)导致逻辑standby同步停止
- Netty中队列(部分)的处理机制
- 阻塞式Http Server与非阻塞式(异步)HttpServer 示例(基于apache http包构建)
- Lua学习笔记
- 希特勒的演讲
- hdu 1907——John & hdu 2509——Be the Winner
- k-近邻算法的初步研究