这次,我们将探索更多的HTTP请求和响应标头,以改善下载服务器的实现: Content-lengthRange 。 前者表示下载量很大,后者允许部分下载文件或在我们开始时失败后继续下载。

Content-length响应标头对于跟踪下载进度的客户端非常有用。 如果您在甚至开始流传输字节之前就提前发送了预期的资源大小,则Web浏览器之类的客户端可以显示非常准确的进度条,甚至可以通过测量平均下载速度来估计总下载时间。 如果没有Content-length客户端,则客户端将一直保持下载尽可能长的时间,希望流结束一天。 但是,在某些情况下很难获得准确的内容长度。 例如,也许您从其他下载服务器流式传输资源,或者您的资源被即时压缩并直接发送到Servlet响应。 在这两种情况下,您能做的最好的事情就是实际上将数据本地缓存在磁盘上,弄清楚大小是多少,并在数据可用时开始流式传输。 这与始终流式传输,永远不要完全保留在内存中的建议并不矛盾。 在这种情况下,我们将临时文件存储在磁盘上,但在完全准备好并且知道其大小后仍将流式传输。

从Java的角度来看,提供内容长度非常简单:

private ResponseEntity<Resource> response(FilePointer filePointer, HttpStatus status, Resource body) {return ResponseEntity.status(status).eTag(filePointer.getEtag()).contentLength(filePointer.getSize()).lastModified(filePointer.getLastModified().toEpochMilli()).body(body);
}

请注意,还存在Resource.contentLength()方法,但是不同类型的资源对它的计算方式有所不同,有时会急于读取整个资源。 我有自己的FilePointer抽象,知道我们要下载的文件大小。

Range标头是RFC 7233中很好描述的HTTP / 1.1的“新”功能。 这个想法是客户端可以仅请求一部分资源(就字节范围而言),主要有两个原因:

  • 先前的下载已中断,我们不想重复相同的工作。 在这种情况下,客户端知道收到了多少字节并要求剩余部分
  • 我们正在流式传输数据(例如视频),我们想跳过某些部分。 考虑一下像Youtube这样的在线播放器,然后点击进度条中间的。 客户可以简单地估计它现在需要的文件部分,与电影持续时间成比例。

并非所有服务器都需要实现Range请求,因此需要进行一些协商。 第一个客户端发送一个请求,仅请求文件的一部分,在此示例中为前100个字节:

> GET /big_buck_bunny_1080p_surround.avi HTTP/1.1
> Range: bytes=0-99
...

如果目标服务器支持范围请求,则响应206 Partial Content

< HTTP/1.1 206 Partial Content
< Last-Modified: Tue, 06 May 2008 11:21:35 GMT
< ETag: "8000089-375a6422-44c8e0d0f0dc0"
< Accept-Ranges: bytes
< Content-Length: 100
< Content-Range: bytes 0-99/928670754

这里有很多有趣的标题。 首先是206,而不是通常的200 OK。 如果为200 OK,则客户端必须假定服务器不支持范围请求。 示例服务器的运行情况非常好,它还会向我们发送Last-ModifiedETag标头,以改善缓存。 另外,服务器通过发送Accept-Ranges标头确认其能够处理Range请求。 当前仅广泛使用bytes ,但是RFC将来允许其他范围单位(秒?帧?)最后两个标头是最有趣的。 Content-Length不再声明资源的总大小,而是我们请求的范围的大小,在这种情况下为100字节。 完整资源的大小以Content-Range编码: bytes 0-99/928670754 。 就我们收到的内容而言,服务器非常精确:前100个字节( 0-99 ),而总资源大小为928670754 。 知道客户端的总大小后,基本上可以请求多个文件中的文件部分。

Range请求的规范具有很大的灵活性,例如我们可以在一个请求中请求多个范围,例如:

> GET /big_buck_bunny_1080p_surround.avi HTTP/1.1
> Range: bytes=0-9,1000-1009
...
< HTTP/1.1 206 Partial Content
< Accept-Ranges: bytes
< Content-Type: multipart/byteranges; boundary=5187ab27335732
<--5187ab27335732
Content-type: video/x-msvideo
Content-range: bytes 0-9/928670754[data]
--5187ab27335732
Content-type: video/x-msvideo
Content-range: bytes 1000-1009/928670754[data]
--5187ab27335732--

但是,服务器可以自由地优化多个范围请求,例如重新布置它们,合并等。从头开始实现部分请求超出了本文的范围,我希望您不必自己做。 例如,从4.2.x开始的Spring对静态资源的部分请求具有全面的内置支持,请参阅: ResourceHttpRequestHandler第463行 。

编写下载服务器

  • 第一部分:始终流式传输,永远不要完全保留在内存中
  • 第二部分:标头:Last-Modified,ETag和If-None-Match
  • 第三部分:标头:内容长度和范围
  • 第四部分:有效地实现HEAD操作
  • 第五部分:油门下载速度
  • 第六部分:描述您发送的内容(内容类型等)
  • 这些文章中开发的示例应用程序可在GitHub上找到。

翻译自: https://www.javacodegeeks.com/2015/07/writing-a-download-server-part-iii-headers-content-length-and-range.html

编写下载服务器。 第三部分:标头:内容长度和范围相关推荐

  1. 502无法解析服务器标头_编写下载服务器。 第三部分:标头:内容长度和范围...

    502无法解析服务器标头 这次,我们将探索更多HTTP请求和响应标头,以改善下载服务器的实现: Content-length和Range . 前者表示下载量很大,后者允许部分下载文件,或者从我们开始的 ...

  2. 服务器编写_编写下载服务器。 第六部分:描述您发送的内容(内容类型等)...

    服务器编写 就HTTP而言,客户端下载的只是一堆字节. 但是,客户真的很想知道如何解释这些字节. 它是图像吗? 还是ZIP文件? 本系列的最后一部分描述了如何向客户端提示她下载的内容. 设置 内容类型 ...

  3. 502无法解析服务器标头_编写下载服务器。 第二部分:标头:Last-Modified,ETag和If-None-Match...

    502无法解析服务器标头 客户端缓存是万维网的基础之一. 服务器应通知客户端资源的有效性,客户端应尽可能快地对其进行缓存. 如我们所见,如果不缓存Web,它将非常缓慢. 只需在任何网站上Ctrl + ...

  4. 编写下载服务器。 第二部分:标头:Last-Modified,ETag和If-None-Match

    客户端缓存是万维网的基础之一. 服务器应告知客户端资源的有效性,客户端应尽可能快地对其进行缓存. 如我们所见,如果不缓存Web,将会非常慢. 只需在任何网站上Ctrl + F5并将其与普通F5进行比较 ...

  5. 编写下载服务器。 第六部分:描述您发送的内容(内容类型等)

    就HTTP而言,客户端下载的只是一堆字节. 但是,客户真的很想知道如何解释这些字节. 它是图像吗? 或者也许是ZIP文件? 本系列的最后一部分描述了如何向客户端提示她下载的内容. 设置 内容类型描述了 ...

  6. mwc校准油门_编写下载服务器。 第五部分:油门下载速度

    mwc校准油门 在僵尸网络时代,您可以租用几百美元来运行自己的分布式拒绝服务攻击,拥有紧急开关来有选择地关闭昂贵的功能或严重降低性能是一个巨大的胜利. 在缓解问题的同时,您的应用程序仍可运行. 当然, ...

  7. 服务器禁止head 请求_编写下载服务器。 第四部分:有效地执行HEAD操作

    服务器禁止head 请求 HEAD是一个经常被遗忘的HTTP方法(动词),其行为类似于GET,但不返回正文. 您使用HEAD来检查资源的存在(如果不存在,它应该返回404),并确保您的缓存中没有陈旧的 ...

  8. grpc 流式传输_编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中...

    grpc 流式传输 下载各种文件(文本或二进制文件)是每个企业应用程序的生死攸关的事情. PDF文档,附件,媒体,可执行文件,CSV,超大文件等.几乎每个应用程序迟早都必须提供某种形式的下载. 下载是 ...

  9. 编写下载服务器。 第五部分:油门下载速度

    在僵尸网络时代,您可以租用几百美元来运行自己的分布式拒绝服务攻击,拥有紧急开关有选择地关闭昂贵的功能或极大地降低性能是一个巨大的胜利. 在缓解问题的同时,您的应用程序仍可运行. 当然,这种安全措施在高 ...

最新文章

  1. 机器学习中的参数与非参数方法
  2. 《从零构建前后分离web项目》:开篇 - 纵观WEB历史演变
  3. springmvc DispatchServlet初始化九大加载策略(二)
  4. ML之FE:pandas库中数据分析利器之groupby分组函数、agg聚合函数、同时使用groupby与agg函数组合案例之详细攻略
  5. 编写程序将一行英文中指定的字符串替换为另一字符串后输出。注意:查找指定字符串_python 3 笔记(一)...
  6. 课后作业之字符串加密
  7. .NET Framewrok 4.0新增类库
  8. 富文本编辑器quill的集成
  9. 看视频学编程之WinForm
  10. [转载] Python中对 Excel 的相关详细操作(读取、写入、指定行、指定列、新增sheet工作表)
  11. Access、CorelDRAW总结
  12. sqlite如何与mysql连接数据库连接_c#中怎么连接到sqlite数据库?
  13. atitit.taskService 任务管理器的设计 v1
  14. C语言-第19课 - #pragma预处理分析
  15. 20190301小中大
  16. 手机及电脑的护眼模式开启
  17. java+websocket实现网页聊天室
  18. CIPP非开挖修复技术|UV紫外光与传统水翻CIPP修复对比分析
  19. 如何用浏览器测试post请求
  20. python爬虫——利用 session 处理登录状态 github 登录实例

热门文章

  1. jQuery遍历div,判断是否为空,为空时执行某个操作
  2. ReactiveLodeBalancerClientFilter响应式负载均衡代理
  3. 命令点无效怎么处理_CAD执行修改命令,你试过重复选择对象吗?
  4. controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......
  5. 编程猜单词游戏python_Python实现简单的猜单词小游戏
  6. eclipse maven 项目发布到tomcat 报错 Failed to scan JAR [file:/C:/xxxxx.jar] from WEB-INF/lib
  7. ibatis(2)ibatis是什么
  8. libreoffice_利用Excel或LibreOffice的业务输入进行单元测试约束
  9. lucene 查询示例_高级Lucene查询示例
  10. java8 streams_Java SE 8新功能介绍:使用Streams API处理集合