我弄了一个,结果怎么都传不上去文件,很痛苦啊
post do user = User.new user.photo = params[:photo] user.save end
photo = { "file_data": base64.encodestring(open("default.jpg", 'rb').read()), "filename": "default.jpg", }
然后用 python 送了个 photo 字段过去了……
你的做法,把二进制文件转换成 Base64 格式,然后附上文件名,Post 的方式发给 API,本身就是可行的,没有什么特别之处。
上传不上去的问题是什么?什么地方报错了?有没有 logs?
# -*- encoding: utf-8 -*- require 'securerandom' unless defined?(::SecureRandom) require 'mime/types' unless defined?(::MIME::Types) module Helpers module File # 根据 RFC 2397 约定,将文件转字符 def file_encode(file_path) return nil unless File.file?(file_path) file = File.open(file_path, 'rb') type = MIME::Types.type_for( File.basename(file_path) ).first.to_s content = Base64.encode64( file.read ) return "data:#{type};base64,#{content}" end # 还原,文件信息 def file_for(file_enc, attr_name) file_info = file_enc.match(/data:(.*);base64,([.\w\s\/\/+]*)/) if file_info && file_info.size == 3 # 文件信息 type = file_info[1] content = file_info[2] # 找扩展名 mime_type = MIME::Types[file_info[1]].first extname = mime_type.extensions.first # 文件名 filename = SecureRandom.hex(10) + ".#{extname}" return { filename: filename, type: type, name: attr_name, tempfile: file_restore(filename, content), head: "Content-Disposition: form-data; name=\"#{attr_name}\"; filename=\"#{filename}\"\r\nContent-Type: #{type}\r\n" } end return nil end # 还原,临时文件 def file_restore(filename, content) temp_file = Tempfile.new(filename, binmode: true) temp_file.write( Base64.decode64(content) ) temp_file.close return temp_file end end end
#1 楼 @lgn21st 那个字段直接被过滤掉了,没有任何错误……
使用 python 的 requests 库上传文件,就解决了
Grape:
desc "update student profile", :params => { "profile[name]" => { desc: "student name" }, "profile[avatar]" => { desc: "student avatar, please send a File", type: "file" } } put "profile" do current_user.student_profile.update_attributes!(params[:profile]) present(current_user, with: ::Entities::User) end
Spec:
it "should update student avatar profile" do avater_path = File.join(Rails.root, "spec/requests/api/GraduationIcon.png") params = { "profile[avatar]" => fixture_file_upload(avater_path, 'image/png') } put "/api/v1/students/profile.json", params, { "HTTP_X_USER_ACCESS_TOKEN" => @access_token } response.code.should == '200' response_body = JSON.parse(response.body) @student.reload @student.profile.avatar.file.filename.should == "GraduationIcon.png" end