将图像通过API发送到Ruby on Rails(RoR)应用程序涉及以下几个核心概念:
使用HTTP客户端(如JavaScript的Fetch API或cURL)发送图像:
// JavaScript示例
async function uploadImage(file) {
const formData = new FormData();
formData.append('image', file);
try {
const response = await fetch('https://your-rails-app.com/api/images', {
method: 'POST',
body: formData,
// 注意: 不要手动设置Content-Type,浏览器会自动设置multipart/form-data
});
const result = await response.json();
console.log('Upload success:', result);
} catch (error) {
console.error('Upload failed:', error);
}
}
// 调用示例
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
uploadImage(e.target.files[0]);
});
在Gemfile中添加:
gem 'paperclip'
然后运行 bundle install
假设我们有一个Image
模型:
# app/models/image.rb
class Image < ApplicationRecord
has_attached_file :attachment,
styles: { medium: "300x300>", thumb: "100x100>" },
default_url: "/images/:style/missing.png"
validates_attachment_content_type :attachment, content_type: /\Aimage\/.*\z/
end
# app/controllers/api/images_controller.rb
class Api::ImagesController < ApplicationController
skip_before_action :verify_authenticity_token
def create
@image = Image.new(image_params)
if @image.save
render json: {
status: 'success',
url: @image.attachment.url,
thumb_url: @image.attachment.url(:thumb)
}, status: :created
else
render json: {
status: 'error',
errors: @image.errors.full_messages
}, status: :unprocessable_entity
end
end
private
def image_params
params.permit(:attachment)
end
end
# config/routes.rb
namespace :api do
resources :images, only: [:create]
end
由于回形针已停止维护,推荐使用Rails内置的Active Storage:
rails active_storage:install
rails db:migrate
# app/models/image.rb
class Image < ApplicationRecord
has_one_attached :file
end
class Api::ImagesController < ApplicationController
def create
@image = Image.new
@image.file.attach(params[:file])
if @image.save
render json: {
url: url_for(@image.file),
status: 'success'
}
else
render json: {
errors: @image.errors.full_messages,
status: 'error'
}, status: :unprocessable_entity
end
end
end
问题:默认情况下,Rails有文件大小限制
解决方案:
client_max_body_size
# config/initializers/rack_attack.rb
Rack::Attack.throttle('limit file uploads', limit: 1, period: 1.second) do |req|
req.ip if req.path == '/api/images' && req.post?
end
解决方案: 使用rack-cors gem
# Gemfile
gem 'rack-cors'
# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '/api/*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
expose: ['Authorization']
end
end
解决方案:
# 使用Active Storage时
validate :acceptable_file
private
def acceptable_file
return unless file.attached?
unless file.byte_size <= 10.megabyte
errors.add(:file, "is too big")
end
acceptable_types = ["image/jpeg", "image/png"]
unless acceptable_types.include?(file.content_type)
errors.add(:file, "must be a JPEG or PNG")
end
end
通过这种方式,您可以构建一个可靠、安全的图像上传API,供各种客户端应用程序使用。
没有搜到相关的文章