上一篇文章讲到了http文件传输的优化点,我们就看一下如何处理文件内容的传输优化,这里因为是Netty专栏所以我还是用Netty来演示如何做http文件传输优化。我再次强调一下netty为我们提供了丰富的类库和编解码能力,哪怕我们用其它语言比如go这种去做思路还是一样的。我将分两块内容来讲解文件传输优化。
1、基于netty的ChunkedFile做伪chunk传输优化
我们看一下ChunkedFile定义的构造函数
public ChunkedFile(RandomAccessFile file, long offset, long length, int chunkSize)
file 要发送的文件
offset 表示文件内容偏移量如果是从文件起始位置开始读取那么就设置成0
length 表示长度我们整体要发送的数据长度
chunkSize 分块大小表示每次读取多少内容
⭐️(1)我们是要做文件传输这里我们要设置http的content-type
response.headers().set(HttpHeaderNames.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
⭐️(2)如果http是keep-alive方式我们需要设置content-length来告诉浏览器文件大小
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,fileLength);
🚩 前置过程准备完成后我们就需要使用ChunkedFile来分块发送我们的文件内容了
channel.writeAndFlush(new ChunkedFile(file, 0, fileLength, 1024))
2、基于http chunk协议发送文件数据
⭐️ 关键点在于设置transfer-encoding告诉浏览器我要使用chunked方式发送内容,这里注意如果使用chunked方式发送内容就不需要再设置content-length数据内容了。
response.headers().set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
⭐️ 分块内容发送
ByteBuf buf = channel.alloc().buffer();
buf.writeBytes(chunked内容);
this.channel.writeAndFlush(buf);
⭐️ 发送结束标识(因为使用的是chunked模式一定要通过结束标识告诉浏览器http的内容已经发送完成)
this.channel.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
我们看一下上面的处理过程是不是非常简单😄,那我们思考一下🤔为什么发送内容的时候我并没有去封装http chunked协议的内容,是因为netty已经在HttpObjectEncoder类里面帮我们做好处理了,下面我们看一下源码就知道了。
if (contentLength > 0) {
//首先我们把chunked长度转换成hex字符串,再将长度字符串写入缓冲区。
String lengthHex = Long.toHexString(contentLength);
ByteBuf buf = ctx.alloc().buffer(lengthHex.length() + 2);
buf.writeCharSequence(lengthHex, CharsetUtil.US_ASCII);
//写入chunk长度分隔符
ByteBufUtil.writeShortBE(buf, CRLF_SHORT);
将长度信息写入out
out.add(buf);
//写入数据内容到out
out.add(encodeAndRetain(msg));
//写入结束标识到out
out.add(CRLF_BUF.duplicate());
}
🚀 Http chunk优化文件传输-原理 juejin.cn/post/724769…