2011-01-16 10 views
13

पर लिखते हैं, मैं अपने रेल 3 ऐप में फोटो अपलोड करने के लिए Ajax-Upload को लागू करने पर काम कर रहा हूं। प्रलेखन कहते हैं:रेल 3 को कच्चे पोस्ट डेटा मिलते हैं और इसे tmp फ़ाइल

  1. For IE6-8, Opera, older versions of other browsers you get the file as you normally do with regular form-base uploads.

  2. For browsers which upload file with progress bar, you will need to get the raw post data and write it to the file.

तो, कैसे मैं अपने नियंत्रक में कच्चे पद डेटा प्राप्त है और यह एक tmp फ़ाइल पर लिखने तो मेरे नियंत्रक तो यह प्रोसेस कर सकते हैं कर सकते हैं? कुछ अतिरिक्त जानकारी (मेरे मामले में नियंत्रक कुछ छवि हेरफेर कर रहा है और एस 3 के लिए बचत।)

:

मैं सही कॉन्फ़िगर किया गया कर रहा हूँ के रूप में अब के बाद इन मानकों से गुजर रहा है:

Parameters: 
{"authenticity_token"=>"...", "qqfile"=>"IMG_0064.jpg"} 

... और बनाएं कार्रवाई इस तरह दिखता है:

def create 
    @attachment = Attachment.new 
    @attachment.user = current_user 
    @attachment.file = params[:qqfile] 
    if @attachment.save! 
     respond_to do |format| 
      format.js { render :text => '{"success":true}' } 
     end 
    end 
end 

... लेकिन मैं इस त्रुटि मिलती है:

ActiveRecord::RecordInvalid (Validation failed: File file name must be set.): 
    app/controllers/attachments_controller.rb:7:in `create' 
+0

मैंने अभी रेलवे में AJAX अपलोड का एक उदाहरण जारी किया है 3 + यहां अपलोड करें: https://github.com/apneadiving/Pic-upload---Crop-in-Ajax। उम्मीद है कि यह – apneadiving

उत्तर

26

ऐसा इसलिए है क्योंकि पैरा [: qqfile] अपलोड किए गए फ़ाइल ऑब्जेक्ट नहीं है लेकिन एक स्ट्रिंग जिसमें फ़ाइल नाम है। फ़ाइल की सामग्री अनुरोध के निकाय में संग्रहीत है (request.body.read का उपयोग करके सुलभ)। अवांछित, आप पिछड़े संगतता को नहीं भूल सकते हैं, इसलिए आपको अभी भी अपलोडेडफ़ाइल का समर्थन करना होगा।

def create 
    ajax_upload = params[:qqfile].is_a?(String) 
    filename = ajax_upload ? params[:qqfile] : params[:qqfile].original_filename 
    extension = filename.split('.').last 
    # Creating a temp file 
    tmp_file = "#{Rails.root}/tmp/uploaded.#{extension}" 
    id = 0 
    while File.exists?(tmp_file) do 
    tmp_file = "#{Rails.root}/tmp/uploaded-#{id}.#{extension}"   
    id += 1 
    end 
    # Save to temp file 
    File.open(tmp_file, 'wb') do |f| 
    if ajax_upload 
     f.write request.body.read 
    else 
     f.write params[:qqfile].read 
    end 
    end 
    # Now you can do your own stuff 
end 
+4

धन्यवाद मदद कर सकता है! यह बहुत अच्छा काम किया! एक टिप्पणी के रूप में, मैंने पाया (मुझे सही रास्ते पर सेट करने के बाद) कि मेरे मामले में कम से कम 'tmp_file = Tempfile.new (फ़ाइल नाम)' # के तहत अपने कोड की तुलना में थोड़ा क्लीनर होने के दौरान समान रूप से अच्छी तरह से काम करता है '# एक अस्थायी बनाना फ़ाइल 'नोट। दोनों तरीके ठीक काम करते हैं। धन्यवाद! – Andrew

+0

'f.write params [: qqfile] .read' - यह' f.write params होना चाहिए [: qqfile] .tempfile.read' अन्यथा कोई फ़ाइल संग्रहीत नहीं है – Toshe

+0

नहीं, यह नहीं होना चाहिए, अपलोड किया गयाफ़ाइल # पढ़ना एक शॉर्टकट है अपलोड किया गया फ़ाइल # tempfile.read ताकि कोड दोनों मामलों में समान हो –

5

यह कोशिश, lib/qq_file.rb जोड़ें:: assets_controller इस प्रकार में

# encoding: utf-8 
require 'digest/sha1' 
require 'mime/types' 

# Usage (paperclip example) 
# @asset.data = QqFile.new(params[:qqfile], request) 
class QqFile < ::Tempfile 

    def initialize(filename, request, tmpdir = Dir::tmpdir) 
    @original_filename = filename 
    @request = request 

    super Digest::SHA1.hexdigest(filename), tmpdir 
    fetch 
    end 

    def self.parse(*args) 
    return args.first unless args.first.is_a?(String) 
    new(*args) 
    end 

    def fetch 
    self.write @request.raw_post 
    self.rewind 
    self 
    end 

    def original_filename 
    @original_filename 
    end 

    def content_type 
    types = MIME::Types.type_for(@request.content_type) 
     types.empty? ? @request.content_type : types.first.to_s 
    end 
end 

तो इससे पहले कि आप एक समान तरीके से फ़ाइल पर कार्रवाई कर सकते हैं दोनों ही मामलों को पकड़ने के लिए है :

def create 
    @asset ||= Asset.new(params[:asset]) 

    @asset.assetable_type = params[:assetable_type] 
    @asset.assetable_id = params[:assetable_id] || 0 
    @asset.guid = params[:guid] 
    @asset.data = QqFile.parse(params[:qqfile], request) 
    @asset.user_id = 0 
    @success = @asset.save 

    respond_with(@asset) do |format| 
    format.html { render :text => "{'success':#{@success}}" } 
    format.xml { render :xml => @asset.to_xml } 
    format.js { render :text => "{'success':#{@success}}"} 
    format.json { render :json => {:success => @success} } 
    end 
end 

जावास्क्रिप्ट:

var photo_uploader = new qq.FileUploader({ 
    element: document.getElementById('photo-button'), 
    multiple: true, 
    action: '/assets', 
    allowedExtensions: ['png', 'gif', 'jpg', 'jpeg'], 
    sizeLimit: 2097152, 
    params: {guid: $('#idea_guid').val(), assetable_type: 'Idea', klass: 'Picture', collection: true} 
}); 
0

कुछ अव्यवस्था temp फ़ाइल बनाने के बजाय, आप स्ट्रिंगियो का उपयोग कर सकते हैं।

gem 'rack-raw-upload', :git => 'git://github.com/tb/rack-raw-upload.git' 

और config.ru में:

require 'rack/raw_upload' 
use Rack::RawUpload 

और पैरामीटर का उपयोग मेरा उत्तर CarrierWave के बारे में, यहाँ देखें: https://stackoverflow.com/a/8812976/478354

1

एक अन्य समाधान है: नियंत्रक में [फ़ाइल]।

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