2012-03-18 11 views
27

मुझे पता है कि इस तरह के प्रश्न हैं, लेकिन मुझे अभी तक कोई अच्छा जवाब नहीं मिला है। छवि, पेपर क्लिप लगाव: मैं क्या करने की जरूरत है मेरी बनाने तरीकों में से एक है, जो एक बुलाया सहित कुछ अलग-अलग विशेषताओं में शामिल करने के लिए एक वस्तु का वर्णन भेज हैएक रेल में फ़ाइलों को भेजना JSON API

has_attached_file :image 

अब मैं उस छवि को भेजने पढ़ा है बेस 64 के रूप में छवि को एन्कोडिंग और डीकोड करके JSON में सीधे किया जा सकता है, लेकिन यह मेरे लिए एक गंदे समाधान की तरह लगता है। बेहतर तरीके होना चाहिए।

एक और समाधान एक मल्टीपार्ट/फॉर्म-डेटा अनुरोध भेज रहा है, एक LEEjava describes here. की तरह यह समस्या यह है कि अनुरोध पैराम्स रेल 3.2.2 में सही ढंग से व्याख्या नहीं किए जाते हैं, और JSON.parse त्रुटि को थकाता है यह पैराम्स को पार्स करने की कोशिश करता है, या शायद यह रेल है जो कुछ गलत व्याख्या कर रहा है।

Started POST "/api/v1/somemodel.json?token=ZoipX7yhcGfrWauoGyog" for 127.0.0.1 at 2012-03-18 15:53:30 +0200 Processing by Api::V1::SomeController#create as JSON Parameters: {"{\n
\"parentmodel\": {\n \"superparent_id\": 1,\n
\"description\": \"Enjoy the flower\",\n \"\": "=>{"\n
{\n \"someattribute\": 1,\n
\"someotherattribute\": 2,\n \"image\": \"image1\"\n
}\n "=>{"\n }\n}"=>nil}}, "token"=>"ZoipX7yhcGfrWauoGyog"}

इसे पढ़ने के लिए काफी मुश्किल है, क्षमा करें। JSON.parse (पैरामीटर [: parentmodel]) संभव नहीं यहाँ है, और मैं नहीं कर सकता JSON.parse (पैरामीटर) क्योंकि या तो टोकन विशेषता का, JSON.parse (पैरामीटर) इस त्रुटि फेंकता है:

TypeError (can't convert ActiveSupport::HashWithIndifferentAccess into String)

जो मुझे विश्वास दिलाता है कि मैं या तो इस समस्या को पूरी तरह गलत कर रहा हूं, या मैं बस कुछ कर रहा हूं। किसी भी तरह से, हम यह सुनिश्चित कर सकते हैं कि मैं कुछ के बारे में गलत हूं। :)

क्या ऐसा करने का कोई बेहतर तरीका है? क्या कोई मुझे किसी गाइड/ट्यूटोरियल पर इंगित कर सकता है, या एक उत्तर लिख सकता है कि मुझे यह कैसे करना चाहिए?

अग्रिम धन्यवाद

अद्यतन: इसलिए मैं वास्तव में अब काम मिल गया है, लेकिन केवल परीक्षण में। मुझे पूरा यकीन नहीं है कि यह कैसे काम करता है, लेकिन शायद कोई मेरे लिए अंतराल भर सकता है? यह परीक्षण कोड का हिस्सा है (छवि: fixture_file_upload (...) महत्वपूर्ण हिस्सा है)।

parts_of_the_object = { someattribute: 0, someotherattribute: 0, image: fixture_file_upload('/images/plot.jpg', 'image/jpg') } 

मेरे पैरामीटर [] एक सामान्य HTML रूप की तरह दिखता है प्रस्तुत की गई थी, जो अजीब (और भयानक) है:

Parameters: {"superparentid"=>"1", "plots"=>[{"someattribute"=>"0", "someotherattribute"=>"0", "image"=>#<ActionDispatch::Http::UploadedFile:0x007f812eab00e8 @original_filename="plot.jpg", @content_type="image/jpg", @headers="Content-Disposition: form-data; name=\"plots[][image]\"; filename=\"plot.jpg\"\r\nContent-Type: image/jpg\r\nContent-Length: 51818\r\n", @tempfile=#<File:/var/folders/45/rcdbb3p50bl2rgjzqp3f0grw0000gn/T/RackMultipart20120318-1242-1cn036o>>}], "token"=>"4L5LszuXQMY6rExfifio"} 

अनुरोध जैसे और पोस्ट अनुरोध rspec साथ किया जाता है बना है:

post "/api/v1/mycontroller.json?token=#{@token}", thefull_object 

तो मुझे यह सब काम मिल गया है। मुझे नहीं पता कि यह वास्तव में कैसे काम करता है! मैं खुद ही इस तरह की प्रतिक्रिया बनाने में सक्षम होना चाहता हूं, न केवल आरएसपीसी से। :-)

उत्तर

38

मुझे वास्तव में कुछ सवाल करने के लिए कल इस प्रश्न के साथ एक भयानक समय था। असल में, मैंने प्रश्न लिखा: Base64 upload from Android/Java to RoR Carrierwave

नियंत्रक में अपलोड की गई छवि ऑब्जेक्ट को बनाने के लिए यह नीचे आया और फिर इसे पैराम में वापस इंजेक्शन दिया गया।

इस विशिष्ट उदाहरण के लिए, हम बेस 64 फ़ाइल ले रहे हैं (जो मुझे लगता है कि आपके पास है, क्योंकि JSON एम्बेडेड फ़ाइलों का समर्थन नहीं करता है) और सिस्टम में एक temp फ़ाइल के रूप में सहेज रहा है, तो हम उस अपलोड किए गए फ़ाइल ऑब्जेक्ट को बना रहे हैं और अंत में इसे पैराम में फिर से डालना।

picture {:user_id => "1", :folder_id => 1, etc., :picture_path {:file => "base64 awesomeness", :original_filename => "my file name", :filename => "my file name"}} 

यहाँ मेरी नियंत्रक अब कैसा दिखता है:

क्या मेरी json/पैरामीटर की तरह लग रहा

# POST /pictures 
    # POST /pictures.json 
    def create 

    #check if file is within picture_path 
    if params[:picture][:picture_path]["file"] 
     picture_path_params = params[:picture][:picture_path] 
     #create a new tempfile named fileupload 
     tempfile = Tempfile.new("fileupload") 
     tempfile.binmode 
     #get the file and decode it with base64 then write it to the tempfile 
     tempfile.write(Base64.decode64(picture_path_params["file"])) 

     #create a new uploaded file 
     uploaded_file = ActionDispatch::Http::UploadedFile.new(:tempfile => tempfile, :filename => picture_path_params["filename"], :original_filename => picture_path_params["original_filename"]) 

     #replace picture_path with the new uploaded file 
     params[:picture][:picture_path] = uploaded_file 

    end 

    @picture = Picture.new(params[:picture]) 

    respond_to do |format| 
     if @picture.save 
     format.html { redirect_to @picture, notice: 'Picture was successfully created.' } 
     format.json { render json: @picture, status: :created, location: @picture } 
     else 
     format.html { render action: "new" } 
     format.json { render json: @picture.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

केवल एक चीज है इस बिंदु पर करने के लिए छोड़ दिया tempfile नष्ट करने के लिए है, जो मुझे विश्वास है कि tempfile.delete

मुझे उम्मीद है कि यह आपके प्रश्न के साथ मदद करता है! मैंने पूरे दिन कल एक समाधान की तलाश में बिताया, और जो कुछ मैंने देखा है वह एक मृत अंत है। हालांकि, यह मेरे परीक्षण मामलों पर काम करता है।

+0

मुझे पता है अगर यह आपके देव/prod मोड में काम नहीं करता है, मैं इस का हल मिल गया कुछ दिन पहले लेकिन forg एक उत्तर लिखने के लिए। यह आपके जैसा बहुत सुंदर है, केवल मैं इसे मॉडल में कर रहा हूं (बेस 64 डेटा को सीधे image_data विशेषता में भेज रहा हूं)। मुझे आपके समाधान को और अधिक पसंद है। मुझे बताएं कि यह कैसे जाता है और अगर मैं कर सकता हूं तो मैं मदद करूंगा। –

+0

जो मैं देख सकता हूं उससे जवाब सही है इसलिए मैं बक्षीस दे रहा हूं। –

+0

यह एक अच्छा जवाब है, लेकिन कम से कम रेल 3/रूबी 1.9 में कुछ मामूली छेद हैं। सबसे पहले, सुनिश्चित करें कि आप लिखने के बाद 'tempfile.rewind()' सुनिश्चित करें, अन्यथा आपको 0 लंबाई वाली फाइलें मिलेंगी। – Shannon

8

टॉमजे ने एक अच्छा जवाब दिया, लेकिन कम से कम रेल 3/रूबी 1.9 में कुछ मामूली छेद हैं।

सबसे पहले, अपने पैराम ऑब्जेक्ट में अपलोड किए गए फ़ाइल ऑब्जेक्ट पर क्या हो सकता है [] पर कॉल करने का प्रयास न करें। सुनिश्चित करें कि आप इसे .is_a?(Hash) पहले देखें, उदाहरण के लिए।

इसके अलावा, सुनिश्चित करें कि आप tempfile.rewind() लिखने के बाद सुनिश्चित करें, अन्यथा आपको 0 लंबाई वाली फ़ाइलें मिलेंगी।

:original_filename अपलोड किए गए फ़ाइल के निर्माता के पैरामीटर में कुंजी अनावश्यक/अप्रयुक्त है। दूसरी ओर, आप :type कुंजी प्रदान करना चाह सकते हैं। एक आसान तरीका है प्रकार के लिए मूल्य को खोजने के लिए mime_type = Mime::Type.lookup_by_extension(File.extname(original_filename)[1..-1]).to_s

यहाँ एक संस्करण में परिवर्तन के साथ लागू किया है:

# POST /pictures 
# POST /pictures.json 
def create 

    #check if file is within picture_path 
    if params[:picture][:picture_path].is_a?(Hash) 
    picture_path_params = params[:picture][:picture_path] 
    #create a new tempfile named fileupload 
    tempfile = Tempfile.new("fileupload") 
    tempfile.binmode 
    #get the file and decode it with base64 then write it to the tempfile 
    tempfile.write(Base64.decode64(picture_path_params["file"])) 
    tempfile.rewind() 

    mime_type = Mime::Type.lookup_by_extension(File.extname(original_filename)[1..-1]).to_s 
    #create a new uploaded file 
    uploaded_file = ActionDispatch::Http::UploadedFile.new(
     :tempfile => tempfile, 
     :filename => picture_path_params["filename"], 
     :type => mime_type) 

    #replace picture_path with the new uploaded file 
    params[:picture][:picture_path] = uploaded_file 
    end 

    @picture = Picture.new(params[:picture]) 
    respond_to do |format| 
    if @picture.save 
     format.html { redirect_to @picture, notice: 'Picture was successfully created.' } 
     format.json { render json: @picture, status: :created, location: @picture } 
    else 
    format.html { render action: "new" } 
    format.json { render json: @picture.errors, status: :unprocessable_entity } 
    end 
end 

अंत

+0

{: अवतार => ["पेपरक्लिप :: त्रुटियां :: NotIdentifiedByImageMagickError", "पेपरक्लिप :: त्रुटियां :: NotIdentifiedByImageMagickError"]}> कोई विचार? – ajbraus

संबंधित मुद्दे