progress.rb
上传用户:netsea168
上传日期:2022-07-22
资源大小:4652k
文件大小:5k
源码类别:

Ajax

开发平台:

Others

  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
  7.   # +remaining_seconds+
  8.   #
  9.   # You can get the current +Progress+ object by calling +upload_progress+ instance
  10.   # method in your controller or view.
  11.   #
  12.   class Progress
  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
  19.       # Number of seconds between updates before giving up to try and calculate
  20.       # bitrate anymore
  21.       MIN_STALL_TIME = 10.0   
  22.       # Number of samples used to calculate bitrate
  23.       MAX_SAMPLES = 20         
  24.     end
  25.     # Number bytes received from the multipart post
  26.     attr_reader :received_bytes
  27.     
  28.     # Total number of bytes expected from the mutlipart post
  29.     attr_reader :total_bytes
  30.     
  31.     # The last time the upload history was updated
  32.     attr_reader :last_update_time
  33.     # A message you can set from your controller or view to be rendered in the 
  34.     # +upload_status_text+ helper method.  If you set a messagein a controller
  35.     # then call <code>session.update</code> to make that message available to 
  36.     # your +upload_status+ action.
  37.     attr_accessor :message
  38.     # Create a new Progress object passing the expected number of bytes to receive
  39.     def initialize(total)
  40.       @total_bytes = total
  41.       reset!
  42.     end
  43.     # Resets the received_bytes, last_update_time, message and bitrate, but 
  44.     # but maintains the total expected bytes
  45.     def reset!
  46.       @received_bytes, @last_update_time, @stalled, @message = 0, 0, false, ''
  47.       reset_history
  48.     end
  49.     # Number of bytes left for this upload
  50.     def remaining_bytes
  51.       @total_bytes - @received_bytes
  52.     end
  53.     # Completed percent in integer form from 0..100
  54.     def completed_percent
  55.       (@received_bytes * 100 / @total_bytes).to_i rescue 0
  56.     end
  57.     # Updates this UploadProgress object with the number of bytes received
  58.     # since last update time and the absolute number of seconds since the
  59.     # beginning of the upload.
  60.     # 
  61.     # This method is used by the +MultipartProgress+ module and should
  62.     # not be called directly.
  63.     def update!(bytes, elapsed_seconds)#:nodoc:
  64.       if @received_bytes + bytes > @total_bytes
  65.         #warn "Progress#update received bytes exceeds expected bytes"
  66.         bytes = @total_bytes - @received_bytes
  67.       end
  68.       @received_bytes += bytes
  69.       # Age is the duration of time since the last update to the history
  70.       age = elapsed_seconds - @last_update_time
  71.       # Record the bytes received in the first element of the history
  72.       # in case the sample rate is exceeded and we shouldn't record at this
  73.       # time
  74.       @history.first[0] += bytes
  75.       @history.first[1] += age
  76.       history_age = @history.first[1]
  77.       @history.pop while @history.size > MAX_SAMPLES
  78.       @history.unshift([0,0]) if history_age > MIN_SAMPLE_TIME
  79.       if history_age > MIN_STALL_TIME
  80.         @stalled = true
  81.         reset_history 
  82.       else
  83.         @stalled = false
  84.       end
  85.       @last_update_time = elapsed_seconds
  86.       
  87.       self
  88.     end
  89.     # Calculates the bitrate in bytes/second. If the transfer is stalled or
  90.     # just started, the bitrate will be 0
  91.     def bitrate
  92.       history_bytes, history_time = @history.transpose.map { |vals| vals.inject { |sum, v| sum + v } } 
  93.       history_bytes / history_time rescue 0
  94.     end
  95.     # Number of seconds elapsed since the start of the upload
  96.     def elapsed_seconds
  97.       @last_update_time
  98.     end
  99.     # Calculate the seconds remaining based on the current bitrate. Returns
  100.     # O seconds if stalled or if no bytes have been received
  101.     def remaining_seconds
  102.       remaining_bytes / bitrate rescue 0
  103.     end
  104.     # Returns true if there are bytes pending otherwise returns false
  105.     def finished?
  106.       remaining_bytes <= 0
  107.     end
  108.     # Returns true if some bytes have been received
  109.     def started?
  110.       @received_bytes > 0
  111.     end
  112.     # Returns true if there has been a delay in receiving bytes.  The delay
  113.     # is set by the constant MIN_STALL_TIME
  114.     def stalled?
  115.       @stalled
  116.     end
  117.     private
  118.     def reset_history
  119.       @history = [[0,0]]
  120.     end
  121.   end
  122. end