为什么AWS S3 Ruby客户端上传的是文件路径而非实际图片?
解决方案
问题根源
AWS Ruby SDK 的 put_object 方法的 body 参数如果接收字符串类型值,会直接将字符串本身作为上传对象的内容,不会自动将其解析为本地文件路径读取对应文件内容,这就是你上传后只得到路径文本的原因。
修正方法
方案1:修改现有 put_object 写法
你需要将body参数改为传入文件IO对象,同时建议补充content_type参数明确指定文件MIME类型,保证S3返回正确的资源类型,浏览器可以直接预览图片而不是下载:
def object_uploaded?(s3_client, bucket_name, object_key) # 如果是Rails项目可以用 Rails.root.join("tmp/cosn_img.jpeg") 确保路径正确 file_path = File.expand_path("tmp/cosn_img.jpeg") response = s3_client.put_object( body: File.open(file_path, "rb"), # 以二进制只读模式打开文件传入IO acl: "public-read", bucket: bucket_name, key: object_key, content_type: "image/jpeg" # 明确指定图片类型 ) !!response.etag rescue StandardError => e puts "Error uploading object: #{e.message}" false end
如果是大文件上传,更推荐用块形式打开文件避免资源泄漏:
File.open(file_path, "rb") do |file| response = s3_client.put_object( body: file, # 其余参数保持不变 ) end
方案2:使用更简便的 upload_file 方法
AWS SDK 已经封装了专门用于本地文件上传的upload_file方法,直接传入文件路径即可,无需手动处理IO逻辑,适配大文件自动分片上传,更省心:
def object_uploaded?(bucket_name, object_key) s3_object = Aws::S3::Object.new(bucket_name, object_key, region: 'us-west-2') # 直接传入本地文件路径即可 s3_object.upload_file("tmp/cosn_img.jpeg", acl: "public-read", content_type: "image/jpeg") rescue StandardError => e puts "Error uploading object: #{e.message}" false end
注意事项
- 请确认本地文件路径的正确性,相对路径是相对于你执行Ruby脚本的工作目录,建议用
File.expand_path或者框架提供的根路径方法(如Rails的Rails.root)生成绝对路径避免找不到文件的问题。 - 如果上传的图片格式不固定,可以通过
mime-types等Gem自动获取文件的MIME类型填入content_type参数。
内容的提问来源于stack exchange,提问作者McKay Whiting
相关产品推荐
相关产品推荐

