问题
I'm working on a REST API, trying to upload a picture of user with:
- grape micro-framework
- paperclip gem but it's not working, showing this error
- rails version is 3.2.8
No handler found for #<Hashie::Mash filename="user.png" head="Content-Disposition: form-data; name=\"picture\"; filename=\"user.png\"\r\nContent-Type: image/png\r\n" name="picture" tempfile=#<File:/var/folders/7g/b_rgx2c909vf8dpk2v00r7r80000gn/T/RackMultipart20121228-52105-43ered> type="image/png">
I tried testing paperclip with a controller and it worked but when I try to upload via grape api its not working my post header is multipart/form-data
My code for the upload is this
user = User.find(20)
user.picture = params[:picture]
user.save!
So if it is not possible to upload files via grape is there any alternative way to upload files via REST api?
回答1:
@ahmad-sherif solution works but you loose original_filename (and extension) and that can provide probems with preprocessors and validators. You can use ActionDispatch::Http::UploadedFile
like this:
desc "Update image"
params do
requires :id, :type => String, :desc => "ID."
requires :image, :type => Rack::Multipart::UploadedFile, :desc => "Image file."
end
post :image do
new_file = ActionDispatch::Http::UploadedFile.new(params[:image])
object = SomeObject.find(params[:id])
object.image = new_file
object.save
end
回答2:
Maybe a more consistent way to do this would be to define paperclip adapter for Hashie::Mash
module Paperclip
class HashieMashUploadedFileAdapter < AbstractAdapter
def initialize(target)
@tempfile, @content_type, @size = target.tempfile, target.type, target.tempfile.size
self.original_filename = target.filename
end
end
end
Paperclip.io_adapters.register Paperclip::HashieMashUploadedFileAdapter do |target|
target.is_a? Hashie::Mash
end
and use it "transparently"
user = User.find(20)
user.picture = params[:picture]
user.save!
added to wiki - https://github.com/intridea/grape/wiki/Uploaded-file-and-paperclip
回答3:
You can pass the File
object you got in params[:picture][:tempfile]
as Paperclip got an adapter for File
objects, like this
user.picture = params[:picture][:tempfile]
user.picture_file_name = params[:picture][:filename] # Preserve the original file name
回答4:
For the sake of Rails 5.1 users this should do as well:
/your/endpoint/path
params do
required :avata, type: File
end
users_spec.rb
describe 'PATCH /users:id' do
subject { patch "/api/users/#{user.id}", params: params }
let(:user) { create(:user) }
let(:params) do
{
avatar: fixture_file_upload("spec/fixtures/files/jpg.jpg", 'image/jpeg')
}
end
it 'updates the user' do
subject
updated_user = user.reload
expect(updated_user.avatar.url).to eq(params[:avatar])
end
end
来源:https://stackoverflow.com/questions/14067163/uploading-file-with-grape-and-paperclip