1
module UploadProgress #:nodoc:
2
# Upload Progress abstracts the progress of an upload. It's used by the
3
# multipart progress IO that keeps track of the upload progress and creating
4
# the application depends on. It contians methods to update the progress
5
# during an upload and read the statistics such as +received_bytes+,
6
# +total_bytes+, +completed_percent+, +bitrate+, and
9
# You can get the current +Progress+ object by calling +upload_progress+ instance
10
# method in your controller or view.
13
unless const_defined? :MIN_SAMPLE_TIME
14
# Number of seconds between bitrate samples. Updates that occur more
15
# frequently than +MIN_SAMPLE_TIME+ will not be queued until this
16
# time passes. This behavior gives a good balance of accuracy and load
17
# for both fast and slow transfers.
18
MIN_SAMPLE_TIME = 0.150
20
# Number of seconds between updates before giving up to try and calculate
24
# Number of samples used to calculate bitrate
28
# Number bytes received from the multipart post
29
attr_reader :received_bytes
31
# Total number of bytes expected from the mutlipart post
32
attr_reader :total_bytes
34
# The last time the upload history was updated
35
attr_reader :last_update_time
37
# A message you can set from your controller or view to be rendered in the
38
# +upload_status_text+ helper method. If you set a messagein a controller
39
# then call <code>session.update</code> to make that message available to
40
# your +upload_status+ action.
41
attr_accessor :message
43
# Create a new Progress object passing the expected number of bytes to receive
49
# Resets the received_bytes, last_update_time, message and bitrate, but
50
# but maintains the total expected bytes
52
@received_bytes, @last_update_time, @stalled, @message = 0, 0, false, ''
56
# Number of bytes left for this upload
58
@total_bytes - @received_bytes
61
# Completed percent in integer form from 0..100
63
(@received_bytes * 100 / @total_bytes).to_i rescue 0
66
# Updates this UploadProgress object with the number of bytes received
67
# since last update time and the absolute number of seconds since the
68
# beginning of the upload.
70
# This method is used by the +MultipartProgress+ module and should
71
# not be called directly.
72
def update!(bytes, elapsed_seconds)#:nodoc:
73
if @received_bytes + bytes > @total_bytes
74
#warn "Progress#update received bytes exceeds expected bytes"
75
bytes = @total_bytes - @received_bytes
78
@received_bytes += bytes
80
# Age is the duration of time since the last update to the history
81
age = elapsed_seconds - @last_update_time
83
# Record the bytes received in the first element of the history
84
# in case the sample rate is exceeded and we shouldn't record at this
86
@history.first[0] += bytes
87
@history.first[1] += age
89
history_age = @history.first[1]
91
@history.pop while @history.size > MAX_SAMPLES
92
@history.unshift([0,0]) if history_age > MIN_SAMPLE_TIME
94
if history_age > MIN_STALL_TIME
101
@last_update_time = elapsed_seconds
106
# Calculates the bitrate in bytes/second. If the transfer is stalled or
107
# just started, the bitrate will be 0
109
history_bytes, history_time = @history.transpose.map { |vals| vals.inject { |sum, v| sum + v } }
110
history_bytes / history_time rescue 0
113
# Number of seconds elapsed since the start of the upload
118
# Calculate the seconds remaining based on the current bitrate. Returns
119
# O seconds if stalled or if no bytes have been received
120
def remaining_seconds
121
remaining_bytes / bitrate rescue 0
124
# Returns true if there are bytes pending otherwise returns false
129
# Returns true if some bytes have been received
134
# Returns true if there has been a delay in receiving bytes. The delay
135
# is set by the constant MIN_STALL_TIME