#ruby-on-rails #ruby #amazon-web-services #amazon-s3 #filepath
Вопрос:
TL;DR
Как вы вводите пути к файлам в клиент AWS S3 API Ruby и интерпретируете их как изображения, а не строковые буквальные пути к файлам?
Более Подробная Информация
Я использую клиент Ruby AWS S3 для программной загрузки изображений. Я взял этот код из их примера кода запуска и почти не изменил его сам. Видишь https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/s3-example-upload-bucket-item.html
def object_uploaded?(s3_client, bucket_name, object_key)
response = s3_client.put_object(
body: "tmp/cosn_img.jpeg", # is always interpreted literally
acl: "public-read",
bucket: bucket_name,
key: object_key
)
if response.etag
return true
else
return false
end
rescue StandardError => e
puts "Error uploading object: #{e.message}"
return false
end
# Full example call:
def run_me
bucket_name = 'cosn-images'
object_key = "#{order_number}-trello-pic_#{list_config[:ac_campaign_id]}.jpeg"
region = 'us-west-2'
s3_client = Aws::S3::Client.new(region: region)
if object_uploaded?(s3_client, bucket_name, object_key)
puts "Object '#{object_key}' uploaded to bucket '#{bucket_name}'."
else
puts "Object '#{object_key}' not uploaded to bucket '#{bucket_name}'."
end
end
Это работает и может загружаться в AWS, но он загружает только путь к файлу из тела, а не сам файл.
путь к файлу отображается при нажатии на ссылку вложения
Насколько я могу судить по документации клиента, это должно сработать. https://docs.aws.amazon.com/sdk-for-ruby/v3/api/Aws/S3/Client.html#put_object-instance_method
Кроме того, ручная загрузка этого файла через интерфейс работает просто отлично, так что это должно быть проблемой в моем коде.
Как вы должны сообщить AWS, что он должен интерпретировать этот путь к файлу как путь к файлу, а не просто как строковый литерал?
Комментарии:
1. Используя
upload_file
вместоput_object
. В противном случае вы можете сделатьbody: open("tmp/cosn_img.jpeg", 'r').read()
2. @jordanm Не могли бы вы подробнее рассказать о своем ответе? Я пробовал использовать
body: open("tmp/cosn_img.jpeg", 'r').read()
, но это, похоже, не сработало. Он просто вернул пустую строку. И я не уверен, как подключиться к остальной части процесса и аутентификации.upload_file
3. Вам придется прочитать файл в
'rb'
режиме, а'r'
не в режиме, чтобы он правильно прочитал файл изображения
Ответ №1:
У вас есть две проблемы:
- В конце назначений переменных у вас есть запятые
object_uploaded?
, которые влияют на способ хранения ваших переменных. Уберите это. - Вам нужно ссылаться на файл как на тип объекта файла, а не как на путь к файлу. Подобный этому:
image = File.open("#{Rails.root}/tmp/cosn_img.jpeg")
Смотрите полный код ниже:
def object_uploaded?(image, s3_client, bucket_name, object_key)
response = s3_client.put_object(
body: image,
acl: "public-read",
bucket: bucket_name,
key: object_key
)
puts response
if response.etag
return true
else
return false
end
rescue StandardError => e
puts "Error uploading object: #{e.message}"
return false
end
def run_me
image = File.open("#{Rails.root}/tmp/cosn_img.jpeg")
bucket_name = 'cosn-images'
object_key = "#{order_number}-trello-pic_#{list_config[:ac_campaign_id]}.jpeg"
region = 'us-west-2'
s3_client = Aws::S3::Client.new(region: region)
if object_uploaded?(image, s3_client, bucket_name, object_key)
puts "Object '#{object_key}' uploaded to bucket '#{bucket_name}'."
else
puts "Object '#{object_key}' not uploaded to bucket '#{bucket_name}'."
end
end
Ответ №2:
Их документы кажутся немного странными и не прямыми, но, похоже, вам может потребоваться передать объект file/io вместо пути.
В документах ruby здесь есть такой пример:
s3_client.put_object(
:bucket_name => 'mybucket',
:key => 'some/key'
:content_length => File.size('myfile.txt')
) do |buffer|
File.open('myfile.txt') do |io|
buffer.write(io.read(length)) until io.eof?
end
end
или другой вариант в документах aws ruby sdk в разделе «Потоковая передача файла с диска».:
File.open('/source/file/path', 'rb') do |file|
s3.put_object(bucket: 'bucket-name', key: 'object-key', body: file)
end