8

まず、SO でこれに似た質問がかなりあることを認識しています。この 1 週間で、すべてではないにしてもほとんどの本を読みました。しかし、私はまだこれを機能させることができません。

ユーザーが mp3 ファイルを Amazon S3 にアップロードできるようにする Ruby on Rails アプリを開発しています。アップロード自体は完璧に機能しますが、プログレス バーを使用すると、Web サイトでのユーザー エクスペリエンスが大幅に向上します。

Amazon の公式の aws-sdk gem を使用しています。アップロード プロセス中のコールバックに関するドキュメントを隅々まで調べましたが、何も見つかりませんでした。

ファイルは一度に 1 つずつ直接 S3 にアップロードされるため、メモリにロードする必要はありません。複数のファイルのアップロードも必要ありません。

これを機能させるにはJQueryを使用する必要があるかもしれないと考えましたが、それで問題ありません。私はこれが非常に有望に見えることを発見しました: https://github.com/blueimp/jQuery-File-Upload そして、ここの例に従ってみました: https://github.com/nri/s3_uploader_example

しかし、私はそれをうまく機能させることができませんでした。

aws-sdk のドキュメントでは、ブロックを使用したスト​​リーミング アップロードについても簡単に説明しています。

  obj.write do |buffer, bytes|
     # writing fewer than the requested number of bytes to the buffer
     # will cause write to stop yielding to the block
  end

しかし、これはほとんど役に立ちません。どのように「バッファに書き込む」のですか? 常にタイムアウトになる直感的なオプションをいくつか試しました。また、バッファリングに基づいてブラウザを更新するにはどうすればよいでしょうか?

これに対するより良い、またはより簡単な解決策はありますか?

前もって感謝します。この件について何か助けていただければ幸いです。

4

2 に答える 2

10

ブロックを #write に渡すときに生成される「バッファ」オブジェクトは、StringIO のインスタンスです。#write または #<< を使用してバッファに書き込むことができます。これは、ブロック フォームを使用してファイルをアップロードする例です。

file = File.open('/path/to/file', 'r')

obj = s3.buckets['my-bucket'].objects['object-key']
obj.write(:content_length => file.size) do |buffer, bytes|
  buffer.write(file.read(bytes))
  # you could do some interesting things here to track progress
end

file.close
于 2012-08-27T18:45:42.150 に答える
2

AWS gemのソース コードを読んだ後、アップロードされたチャンクの数に基づいて現在の進行状況を生成するために、マルチパート アップロード メソッドを適応 (またはほぼコピー) しました。

s3 = AWS::S3.new.buckets['your_bucket']

file = File.open(filepath, 'r', encoding: 'BINARY')
file_to_upload = "#{s3_dir}/#{filename}"
upload_progress = 0

opts = {
  content_type: mime_type,
  cache_control: 'max-age=31536000',
  estimated_content_length: file.size,
}

part_size = self.compute_part_size(opts)

parts_number = (file.size.to_f / part_size).ceil.to_i
obj          = s3.objects[file_to_upload]

begin
    obj.multipart_upload(opts) do |upload|
      until file.eof? do
        break if (abort_upload = upload.aborted?)

        upload.add_part(file.read(part_size))
        upload_progress += 1.0/parts_number

        # Yields the Float progress and the String filepath from the
        # current file that's being uploaded
        yield(upload_progress, upload) if block_given?
      end
    end
end

compute_part_size メソッドはここで定義されており、これを次のように変更しました。

def compute_part_size options

  max_parts = 10000
  min_size  = 5242880 #5 MB
  estimated_size = options[:estimated_content_length]

  [(estimated_size.to_f / max_parts).ceil, min_size].max.to_i

end

このコードは Ruby 2.0.0p0 でテストされました

于 2013-07-25T23:00:34.030 に答える