Почему AWS загружает буквальные пути к файлам вместо загрузки изображений?

#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:

У вас есть две проблемы:

  1. В конце назначений переменных у вас есть запятые object_uploaded? , которые влияют на способ хранения ваших переменных. Уберите это.
  2. Вам нужно ссылаться на файл как на тип объекта файла, а не как на путь к файлу. Подобный этому:
 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