Sinatra,上传表单中的进度条
我正在开发一个 Sinatra 应用程序,其中包含一个上传表单,并有一个进度条指示上传已完成的程度。 ryan dahl 描述的过程如下:
HTTP 上传进度条相当混乱 - 它们通常涉及在服务器上运行的进程,跟踪 HTTP 服务器正在写入的临时文件的大小,然后在客户端每隔几秒进行一次 AJAX 调用上传过程中向服务器询问上传进度。
每次上传都有一个随机的session-id
,为了跟踪关联,我在我的应用程序中使用了一个类变量
(我知道,这太可怕了——如果你已经有更好的想法,请告诉我)
configure do
@@assoc = {}
end
我有一个用于上传的 POST
路由,以及一个用于 AJAX 轮询的 GET
路由。 在 POST
路由中,我保存了 session-id
、Tempfile
和总大小的关联。
post '/files' do
tmp = params[:file][:tempfile]
# from here on, @@assoc[@sid] should have a value, even in other routes
@@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] }
File.open("#{options.filesdir}/#{filename}", 'w+') do |file|
file << tmp.read
end
end
在 GET
路由中,我根据 Tempfile
的当前大小计算百分比:
get '/status/:sid' do
h = @@assoc[params[:sid]]
unless h.nil?
percentage = (h[:file].size / h[:size].to_f) * 100
"#{percentage}%"
else
"0%"
end
end
问题是,直到 POST
请求还没有已完成(即,在读取所有 Tempfile
后),h.nil?
返回 true
,这实际上没有意义,因为我刚刚在另一条路线中为 @@assoc[@sid]
分配了一个值。
那么,我在这里缺少什么?
编辑:我尝试过
set :reload, false
set :environment, :product
config { @@assoc ||= { } }
- 我也尝试向它扔一个关系数据库(带有 DataMapper 的 SQLite)
都没有成功。
I'm developing a Sinatra app that consists of an upload form, with a progress bar indicating how much of the upload has completed.
The process, as described by ryan dahl, is the following:
HTTP upload progress bars are rather obfuscated- they typically involve a process running on the server keeping track of the size of the tempfile that the HTTP server is writing to, then on the client side an AJAX call is made every couple seconds to the server during the upload to ask for the progress of the upload.
Every upload has a random session-id
, and to keep track of the association i employ a class variable
in my app (i know, that's horrible -- if you've got better ideas, please tell me)
configure do
@@assoc = {}
end
I have a POST
route for the upload, and a GET
one for the AJAX polling.
Inside the POST
route i save the association of session-id
, Tempfile
, and total size.
post '/files' do
tmp = params[:file][:tempfile]
# from here on, @@assoc[@sid] should have a value, even in other routes
@@assoc[@sid] = { :file => tmp, :size => env['CONTENT_LENGTH'] }
File.open("#{options.filesdir}/#{filename}", 'w+') do |file|
file << tmp.read
end
end
In the GET
route, i calculate the percentage based on the Tempfile
's current size:
get '/status/:sid' do
h = @@assoc[params[:sid]]
unless h.nil?
percentage = (h[:file].size / h[:size].to_f) * 100
"#{percentage}%"
else
"0%"
end
end
The problem is that until the POST
request hasn't completed (i.e., after it has read all of the Tempfile
) the h.nil?
returns true
, which doesn't really make sense as I've just assigned @@assoc[@sid]
a value in the other route.
So, what am I missing here?
EDIT: I've tried
set :reload, false
set :environment, :production
config { @@assoc ||= {} }
- I also tried throwing a relational db at it (SQLite with DataMapper)
Neither worked.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想我明白了问题所在:
tmp = params[:file][:tempfile]
在完全收到文件之前不会返回。I think i got what the problem is:
tmp = params[:file][:tempfile]
doesn't return until the file has been fully received.应该是
should be