Netty 5 提供了 一個ChunkedWriterHandler 來傳送大文件,發送端如下:
添加chunedwriterhandler:
ChannelPipeline
p = ...; p.addLast("streamer", newChunkedWriteHandler
()); p.addLast("handler", new MyHandler());
直接發送文件
Channel
ch = ...; ch.write(newChunkedFile
(new File("video.mkv"));
需要注意的是 ChunkedWriterHandler 必須添加在 發送文件的handler的前面。 也就是先添加了handler,才能調用channel write chunedfile。
接收端的代碼如下,關鍵點是發送端需要提前告知文件大小(File.length),將一個handler添加到所有的handler前面,這樣攔截到文件內容,寫完文件將handler移除。
ctx.pipeline().addFirst(new ChunkedReadHandler(size));
1 class ChunkedReadHandler extends ChannelHandlerAdapter{ 2 private long fileSize; 3 private File file; 4 private FileOutputStream ofs; 5 private long readedSize=0; 6 public ChunkedReadHandler(long size) throws FileNotFoundException{ 7 this.fileSize=size; 8 this.file = new File("C:/2.zip"); 9 ofs=new FileOutputStream(this.file); 10 } 11 @Override 12 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 13 14 ByteBuf buf= (ByteBuf) msg; 15 16 readedSize +=buf.readableBytes(); 17 if(buf.isReadable()){ 18 byte[] bytes=new byte[buf.readableBytes()]; 19 buf.readBytes(bytes); 20 ofs.write(bytes); 21 } 22 23 System.out.println(fileSize + " " + readedSize); 24 25 if(readedSize >= fileSize){ 26 ctx.pipeline().remove(this); 27 ofs.close(); 28 } 29 buf.release(); 30 } 31 }
netty5文檔里channelpipeline的doc給了一幅圖比較清楚的描述了handler的關系,像tcp/ip協議一樣是層次關系
一般的handler添加順序為:
- Protocol Decoder - translates binary data (e.g.
ByteBuf
) into a Java object. - Protocol Encoder - translates a Java object into binary data.
- Business Logic Handler - performs the actual business logic (e.g. database access).
對應的輸入輸出層先添加,再添加下一層的handler。
因此,我們的邏輯層就工作在最高層,抽象度最高也最方便。