janko / uppy-s3_multipart

Provides Ruby endpoints for AWS S3 multipart uploads in Uppy
https://uppy.io/docs/aws-s3/
MIT License
65 stars 21 forks source link

acl: "public-read" doesn't work? Make public url and Download file from s3 #6

Closed parwatcodes closed 5 years ago

parwatcodes commented 5 years ago

Quite confused to make the public url for s3 uploads

s3_options = {
    bucket:            "my-bucket",
    access_key_id:     "XXXX-XXXXX-XXXXX",
    secret_access_key: "XXXXX-XXXXX-XXXX-XXXX",
    region:            "us-west-2",
  }

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'videos', **s3_options),
  store: Shrine::Storage::S3.new(**s3_options),
}

Shrine.plugin :uppy_s3_multipart, options: {
  create_multipart_upload: { acl: "public-read" }, # static
  object_url: -> (request) { { response_content_disposition: "attachment" } }, # dynamic
}

# OR

Shrine.uppy_s3_multipart(:cache, options: {
  create_multipart_upload: { acl: "public-read" }, # static
  object_url: -> (request) { { response_content_disposition: "attachment" } }, # dynamic
})

Tried this but doesn't work

https://asdsds.s3.us-west-2.amazonaws.com/videos/2ad9c2a6sada6cc86132f7e6898e16a45923.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI7EZLZZ5TDHXZKRQ%2F20181211%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20181211T104619Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=ec7b1ce8ca0f00e8242ab63cc30341b6496e34270271e8a2da9371cc80f6f16e

Creates this whole link with expiry, also the bucket is public.

janko commented 5 years ago

Setting acl: "public-read" alone won't cause aws-sdk-s3 to generate public URLs, you also need to set object_url: { public: true } (available from 0.2.0). As of Shrine 2.13 and uppy-s3_multipart 0.2.0 both of these will be automatically taken care of for you if you've configured your Shrine S3 storage to be public:

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'videos', public: true, **s3_options),
  store: Shrine::Storage::S3.new(**s3_options),
}
janko commented 5 years ago

I'm going to close this issue, as the solution above should work and is documented in the README.

parwatcodes commented 5 years ago

After receiving the video URL in. A user can download that video.

<a hred=url download>DOWNLOAD</a> doesn't work. Instead, it plays the video. Is there anything related to the configuration???

ATM I am downloading the video through blob, which doesn't seem to be good.

Is there anything with configuration.

Thank you

janko commented 5 years ago

By default any file you upload to S3 will be shown "inline" if possible instead of downloaded. You can change that via the :content_disposition upload option:

Shrine.plugin :uppy_s3_multipart, options: {
  create_multipart_upload: -> (request) do
    filename = request.params["filename"]
    { content_disposition: "attachment; filename=\"#{CGI.escape(filename)}\"" }
  end
}

The :content_disposition S3 object setting will set the Content-Disposition header when the object is downloaded; attachment means "download", and inline means to show it in the browser if possible.

parwatcodes commented 5 years ago

Thank you that works, I was messed with configuration.

I have one more question related to uppy react regarding hideUploadButton prop. Please, can you have a look?

https://github.com/transloadit/uppy/issues/1193

parwatcodes commented 5 years ago

Everything was working fine. But all of sudden it started to add Expiry on Url, even when using public: true

https://a9videos.s3.us-west-2.amazonaws.com/videos/7307ed1f063abee906f897898oi59375a868eb8.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=AKIAI7EZLZZ5TDHXZKRQ%uo72F20181218%2Fus-west-2%2Fs3%2Faws4_request\u0026X-Amz-Date=20181218T113239Z\u0026X-Amz-Expires=900\u0026X-Amz-SignedHeaders=host\u0026X-Amz-Signature=4e5c1705cda9dfdbef601aa8e20b733019072a66fb0f4c9ad613ff0adfae68e63d7

shrine.rb

require "shrine"
require "shrine/storage/s3"

s3_options = {
  bucket:            AMAZON_CONFIG['aws_s3_videos']['s3_bucket'],
  access_key_id:     AMAZON_CONFIG['aws_key'],
  secret_access_key: AMAZON_CONFIG['aws_secret'],
  region:            AMAZON_CONFIG['aws_s3_videos']['aws_region'],
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'videos', public: true, **s3_options),
  store: Shrine::Storage::S3.new(**s3_options),
}

Shrine.plugin :uppy_s3_multipart # load the plugin

Shrine.plugin :uppy_s3_multipart, options: {
  create_multipart_upload: -> (request) do
    filename = request.params["filename"]
    { content_disposition: "attachment; filename=\"#{CGI.escape(filename)}\"" }
  end
}
janko commented 5 years ago

Are you using Shrine 2.13?

parwatcodes commented 5 years ago

Yes I am

Gemfile

gem 'shrine', '~> 2.13.0'
gem 'uppy-s3_multipart'
janko commented 5 years ago

I forgot to also ask, are you using uppy-s3_multipart version 0.2.0? That's the one that added the feature.

For the record, here is a self-contained example proving that it works with Shrine 2.13.0 and uppy-s3_multipart 0.2.0:

require "shrine"
require "shrine/storage/s3"
require "rack/test_app"

s3_options = { bucket: "my-bucket", stub_responses: true }

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'videos', public: true, **s3_options),
  store: Shrine::Storage::S3.new(**s3_options),
}

Shrine.plugin :uppy_s3_multipart # load the plugin

Shrine.plugin :uppy_s3_multipart, options: {
  create_multipart_upload: -> (request) do
    filename = request.params["filename"]
    { content_disposition: "attachment; filename=\"#{CGI.escape(filename)}\"" }
  end
}

app = Shrine.uppy_s3_multipart(:cache)
test_app = Rack::TestApp.wrap(app)

response = test_app.post("/upload-id/complete", json: {
  "key"   => "foo",
  "parts" => [],
})

JSON.parse(response.body_binary)["location"]
# => "https://my-bucket.s3.us-stubbed-1.amazonaws.com/foo"
parwatcodes commented 5 years ago

Shouldn't gem 'uppy-s3_multipart' fetch the latest version?

Doing gem 'uppy-s3_multipart', '~> 0.2.0' will work

janko commented 5 years ago

Not if you already installed the previous one and have it locked in Gemfile.lock.