ror下文件下载是通过send_file完成的,但是如果使用多线程并支持断点续传的客户端(FlashGet等),send_file是不能正确工作的,原因在于,send_file函数没有对HTTP协议的Range头做相应的支持,并且也不支持HTTP/1.1 206 Partial Content相应
我修改了send_file函数,并做了一个plugin 将起解压到vendor/plugins/就可以了
(必要的地方我都写了注释,欢迎大家提出建议和意见)
module ActionController
module Streaming
protected
def send_file(path, options = {})
raise MissingFile, "Cannot read file #{path}" unless File.file?(path) and File.readable?(path)
options[:length] ||= File.size(path) # 文件长度
options[:filename] ||= File.basename(path) # 文件名称
options[:from] ||= 0 # 首偏移量(从哪里开始下载)
options[:to] ||= options[:length] # 结束位置
m_send_file_headers! options # 设置必要的 http 头
@performed_render = false
if options[:stream]
render :status => options[:status], :text => Proc.new { |response, output|
logger.info "Streaming file #{path}" unless logger.nil?
len = options[:buffer_size] || 8192 # 原来的实现是4K, 不过APUE 上说,8K 要好一些,所有我调整了一下
File.open(path, 'rb') do |file|
file.seek(options[:from].to_i, IO::SEEK_SET) if options[:status] == 206 # 如果是多线程下载,则将流定位到首偏移量位置,从此处开始传输
while buf = file.read(len)
# 这个可以优化一下,只要从from 发送到 to 字节就可以了,但我测试过,不进行这个判断是可以的,客户自己计算并保存问下载的起始位置
# 不过我觉得最好还是要给只发送 from 到 to 字节, 虽然有点麻烦
# 这个功能以后在实现吧
output.write(buf)
end
end
}
else
logger.info "Sending file #{path}" unless logger.nil?
File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
end
end
private
def m_send_file_headers!(options)
options.update(DEFAULT_SEND_FILE_OPTIONS.merge(options))
[:length, :type, :disposition].each do |arg|
raise ArgumentError, ":#{arg} option required" if options[arg].nil?
end
disposition = options[:disposition].dup || 'attachment'
disposition <<= %(; filename="#{options[:filename]}") if options[:filename]
# 先输出一些通用的HTTP头
headers.update(
'Content-Type' => options[:type].strip, # fixes a problem with extra '\r' with some browsers
'Content-Disposition' => disposition,
'Content-Transfer-Encoding' => 'binary'
)
# 判断是否存在Range头,并使用正则表达式匹配得到from 和 to
# 如果匹配成功,则表示客户端使用多线程下载,同时一定要将http status 设置为 206
if request.env['HTTP_RANGE'] =~ /bytes=(\d+)-(\d*)/ then # 注意后一个\d*,有一些多线程客户端并不完全符合http Range 头的要求(例如FlashGet)
options[:from] = $1
options[:to] = $2 unless $2.nil? # 如果客户端不标准,就将 to 设置为文件末尾
# 匹配成功,设置status 为 206
options[:status] = 206
# 一下3个http 头仅在多线程下载是有用
headers['Accept-Ranges'] = 'bytes'
headers['content-Range'] = "bytes #{options[:from]}-#{options[:to]}/#{options[:length]}" # 格式为 bytes from-to/total
headers['Content-Length'] = options[:to].to_i - options[:from].to_i + 1 # 注意 在多线程下载下,Content-Length 为传输的实际字节数(从0开始算起,所有要+1)
else
# 非多现场下载
options[:status] = 200 # 请求正常标志
headers['Content-Length'] = options[:length] # 非多线程下载下,Content-Length为文件长度
end
headers['Cache-Control'] = 'private' if headers['Cache-Control'] == 'no-cache'
end
end
end
用法和老send_file一样
class FileController < ApplicationController
def download
#logger.debug request.env['Range'];
# request.env.each do |key, value|
# logger.debug key + '--------' + value
# end
send_file 'public/jdk.tgz'
end
end
分享到:
- 2007-09-11 13:49
- 浏览 3197
- 评论(3)
- 论坛回复 / 浏览 (2 / 4490)
- 查看更多
相关推荐
在Ruby on Rails(简称ROR)框架下,处理文件的上传与下载是一项常见的需求,尤其是在构建包含媒体内容的应用程序时。本文将基于给定的文件信息,详细阐述如何在Rails应用中实现文件的上传与下载功能,包括数据库...
在提供的压缩包文件中,我们可以看到"Ruby语言中文教程",这暗示了资源可能包含了关于Ruby语言的基础知识和进阶内容,对于学习RoR至关重要。Ruby是RoR的基础,理解其语法和特性对于掌握RoR框架极其关键。 **Ruby...
RoR通常在Unix类操作系统上运行最佳,如RHEL、CentOS、Ubuntu和SuSE Linux。对于AMD Opteron x86_64架构的服务器,SuSE Linux提供了更好的优化。64位操作系统能够充分利用硬件性能,但也会消耗更多内存。 文件系统...
至于提供的压缩包文件"codefans.net",虽然无法直接查看具体内容,但可以推测可能包含了一些示例代码或教程,用于演示如何在ASP.NET环境中实现断点续传和大文件上传。你可以解压并查阅这些文件,以获取更具体的实现...
在深入研究RoR源代码时,建议先从官方文档和开源项目开始,例如GitHub上的Rails项目,这能帮助你理解框架的设计思路和实现细节。同时,参与开源社区,阅读他人的代码和贡献自己的代码,是提升技能和了解最新实践的好...
在CIFAR-10上达到89%的准确率,以及在CIFAR-100上达到72%的准确率,展示了ResNet和Ror模型在处理复杂图像分类任务上的强大能力。相比于其他传统的浅层网络或早期的深度网络,这样的准确率显著提高了模型的性能,表明...
"ror实例"可能指的是在学习或实践中,通过创建一个具体的Rails应用程序来理解和掌握RoR的工作原理和最佳实践。 在Ruby on Rails中,重要知识点包括: 1. **Gemfile与Gemfile.lock**:项目中的Gemfile用于指定项目...
2. 函数式编程元素:支持闭包和块,可以实现简洁的代码结构。 3. 强大的元编程能力:Ruby允许在运行时修改类和对象,增强了灵活性。 **二、Rails框架** 1. MVC架构:Rails将应用程序分为模型(Model)、视图(View...
NULL 博文链接:https://xuxiangpan888.iteye.com/blog/266696
在Ruby on Rails(ROR)开发环境中,安装和配置正确的依赖包是至关重要的。这个压缩包包含了一系列用于ROR框架的基础组件,但不包括Ruby本身。让我们深入了解一下这些包的作用和重要性。 首先,`actionpack`是Rails...
### Windows上搭建Ruby on Rails(ROR)环境详解 ...在实际开发过程中,可能会遇到更多具体的细节问题,建议及时查阅官方文档或其他开发者的经验分享,以便更好地解决问题。希望每位学习者都能顺利踏上Rails开发之旅!
总结来说,配置ROR开发环境包括安装Ruby、Rails,创建ROR项目,以及在Eclipse中设置ROR插件和导入项目。在Eclipse中进行ROR开发,可以充分利用其丰富的功能,提升开发效率。理解并熟练运用ROR的MVC架构和相关工具,...
基于RoR的博客系统,代码风格简单清晰,前后太完善,适合初学者。
Ruby on Rails,是基于Ruby编程语言的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,极大地简化了Web应用的开发过程,尤其在快速原型开发和敏捷开发中表现出色。 在这个图书管理系统中,我们可以...
破解版本的JAR包,放到本地磁盘,ECLIPUS直接用,到JVM设置直接加 -noverify -javaagent:D:\javarebel.jar
7. **多线程编程**:在Windows平台上,多线程技术用于实现并发处理,源码中可能包含线程同步、线程间通信等高级技术。 8. **文件操作和I/O流**:处理文件输入输出是任何程序的基础,源码可能会展示如何读写文件,...
### RoR培训课程PPT知识点概述 #### 一、课程概览与背景介绍 ...RoR以其简洁优雅的语法和强大的生态系统,在Web开发领域占有举足轻重的地位。希望每位学员都能从中受益匪浅,成为优秀的Ruby on Rails开发者。
2. **快速开发**:利用RoR的生产力优势,FreeMIS的开发周期相对较短,能够快速实现功能迭代。 3. **易用性**:RoR的模板引擎和视图层设计使得FreeMIS的用户界面友好,用户体验良好。 4. **社区支持**:RoR拥有庞大的...
在RoR中,模型(Model)负责处理数据和业务逻辑,与数据库交互;视图(View)负责展示用户界面,通常包含HTML、CSS和JavaScript;控制器(Controller)作为模型和视图的中间人,处理用户的请求并协调它们之间的通信...