2012-07-22 10 views
5

का उपयोग कर अमेज़ॅन एस 3 पर सीधे एकाधिक फ़ाइलों को अपलोड करना यह समस्या मुझे कई घंटों तक परेशान कर रही है और मुझे इसका समाधान नहीं मिल रहा है।रेल 3.2 और AJAX (गैर-फ्लैश अपलोड समाधान)

मेरे पास एक रेल 3.2 ऐप है जो उपयोगकर्ताओं को carrierwave_direct, कोहरे, और वाहकवेव (carrierwave_direct के लिए निर्भरता) का उपयोग कर अमेज़ॅन एस 3 खाते में फ़ाइलों को अपलोड करने की अनुमति देता है। Carrierwave_direct का उपयोग करने से उपयोगकर्ता को फ़ाइल को सीधे अमेज़ॅन एस 3 पर पोस्ट करके सर्वर पर अपलोड करने की अनुमति मिलती है (सर्वर प्रोसेसिंग और बड़ी फ़ाइलों के लिए हेरोकू जैसे टाइमआउट्स बचाता है)।

यह ठीक काम करता है यदि आप जो करते हैं वह 1 फ़ाइल का चयन करें, इसे अमेज़ॅन पर अपलोड करें, और एक यूआरएल को रीडायरेक्ट करें जो आप अमेज़ॅन प्रदान करते हैं। यह अमेज़ॅन एस 3 के फॉर्म को पोस्ट करके करता है, और अमेज़ॅन यूआरएल में कुछ पैरा के साथ एक यूआरएल (आप इस यूआरएल को अपने फॉर्म में निर्दिष्ट करते हैं) का जवाब देते हैं, जिसे बाद में आपके मॉडल में अमेज़ॅन पर फाइल के पॉइंटर के रूप में संग्रहीत किया जाता है।

तो जीवन चक्र है: 1 फ़ाइल का चयन करें, अमेज़ॅन को पोस्ट करें, अमेज़ॅन एक यूआरएल के साथ प्रतिक्रिया करता है जो आपको दूसरे पृष्ठ पर भेजता है, और फिर आप अमेज़ॅन फ़ाइल में पॉइंटर के साथ रिकॉर्ड सहेज सकते हैं।

जो मैं समझने की कोशिश कर रहा हूं वह है कि मैं एकाधिक फ़ाइलों को कैसे चुनूं और अपलोड की गई प्रगति को अपलोड और अपडेट कर सकता हूं? मैं इसे शुद्ध जावास्क्रिप्ट (आधुनिक ब्राउज़र द्वारा प्रदान की गई फ़ाइल एपीआई का उपयोग करके) करने की कोशिश कर रहा हूं, इसलिए मुझे कोई तृतीय पक्ष टूल नहीं चाहिए। इसके अलावा, गहराई से सीखने के प्रयास में, मैं किसी भी प्लगइन से परहेज कर रहा हूं और कोड को स्वयं लिखने की कोशिश कर रहा हूं।

कार्यक्षमता मैं प्राप्त करने के लिए कोशिश कर रहा हूँ है:

  1. उपयोगकर्ता फ़ाइल क्षेत्र (या खींचें/ड्रॉप)
  2. उपयोगकर्ता एकाधिक फ़ाइलों का चयन करता है के साथ प्रपत्र देखता है (या तो फ़ाइल क्षेत्र या खींचें/ड्रॉप क्लिक करें)
  3. कतार में प्रत्येक फ़ाइल के ऊपर जावास्क्रिप्ट (कोई सर्वर अभी तक), अपलोड (सिर्फ फ़ाइल नाम और आकार, ब्राउज़र फ़ाइल एपीआई का उपयोग कर)
  4. उपयोगकर्ता फिर एक "अपलोड शुरू" पर क्लिक करना करने के लिए चयनित फ़ाइलों की एक कतार निर्माण बटन
  5. दोहराएं का उपयोग करना एक डी अमेज़ॅन एस 3 को फाइल पोस्ट करें; अमेज़ॅन एक यूआरएल के साथ प्रत्येक व्यक्तिगत पोस्ट का जवाब देगा और उस यूआरएल को जावास्क्रिप्ट के जरिए संभाला जाना चाहिए, मानक अनुरोध के रूप में नहीं; अमेज़ॅन द्वारा प्रदान किया गया यूआरएल एक रिकॉर्ड बनाएगा जो सूचक को अमेज़ॅन फ़ाइल में संग्रहीत करता है; एक बार रिकॉर्ड बनने के बाद, कोड समाप्त होने तक कतार में अगली फ़ाइल में जाता है।

इस बिंदु पर, मैं व्यक्तिगत प्रगति पट्टी के बिना भी कर सकता था; पेज रीफ्रेश के बिना अमेज़ॅन एस 3 पर पोस्ट की गई कई फाइलें प्राप्त करने के लिए मुझे खुशी होगी।

मैं किसी भी रत्न के आंशिक नहीं हूं। मैं वास्तव में डरता हूं कि मुझे लिखना होगा कि मैं स्क्रैच से क्या करना चाहता हूं अगर मैं वास्तव में इसे एक विशिष्ट तरीके से करना चाहता हूं। लक्ष्य AJAX के माध्यम से एक अमेज़ॅन एस 3 खाते में एकाधिक फ़ाइल अपलोड है। समस्या से संपर्क करने के तरीके के बारे में भी सामान्य अवधारणाओं के साथ मैं उत्साहित होगा। मैंने इसे घूमने में कई घंटे बिताए हैं और मुझे बस कोई समाधान नहीं मिला है जो मैं चाहता हूं। किसी भी मदद की बहुत सराहना की जाएगी।

संपादित 2014-03-02

राज पूछा कि मैं अपने कई अपलोड कार्यान्वित किया। यह बहुत लंबा रहा है कि मैंने जो कुछ किया उसके पीछे सभी "क्यों" याद नहीं करते हैं (शायद वैसे भी खराब कोड जैसा कि यह मेरा पहला समय था), लेकिन यह वही है जो मैं चल रहा था।

मैं जिस मॉडल को अपलोड कर रहा था वह एक प्रशंसापत्र था, जिसमें एक संबंधित छवि अमेज़ॅन एस 3 में संग्रहीत की जा रही है।इसने उपयोगकर्ता को कई छवियों का चयन करने की अनुमति दी (मुझे लगता है कि वे वास्तव में छवियों में परिवर्तित पीडीएफ फाइलें थे) और उन्हें स्क्रीन पर खींचें/छोड़ दें। अपलोड करते समय, मैंने एक मॉडल प्रदर्शित किया जिसने उपयोगकर्ता को प्रतिक्रिया दी कि यह कितना समय लगेगा।

मुझे यह याद रखने का नाटक नहीं है कि मैं इनमें से बहुत कुछ कर रहा था, लेकिन अगर यह इसका उपयोग करने में स्वतंत्र महसूस करता है।

# app/views/testimonials/new.html.erb 
<div id="main" class="padded"> 
    <div class="center"> 
    <div id="dropzone"> 
     Click or Drop Files here to Upload 
    </div> 

    <%= form_for @testimonial do |f| %> 
     <div class="field"> 
     <%= file_field_tag :image, multiple: true, name: "testimonial[image]", id: "testimonial_image" %> 
     </div> 
    <% end %> 
    </div> 
</div> 

<div id="mask"></div> 
<div id="modal"> 
    <h1> 
    Uploading <span id="global-upload-count">0</span> Files... 
    </h1> 
    <div id="global-progress"> 
    <div id="global-progress-bar" style="width: 0%"> 
     <div id="global-progress-percentage">0%</div> 
    </div> 
    </div> 
    <div id="global-processing"> 
    <span class="spinner"></span> Processing...<span id="global-processing-count">0</span> sec 
    </div> 
</div> 

<script id="template-upload" type="text/x-tmpl"> 
    <div class="upload"> 
    {%=o.name%} ({%=o.readable_size%}) 
    <div class="float-right percentage"></div> 
    <div class="progress"><div class="bar" style="width: 0%"></div></div> 
    </div> 
</script> 

और जे एस:

# Gemfile 
# For client-side multiple uploads 
gem "jquery-fileupload-rails" 

# For file uploads and Amazon S3 storage 
gem "rmagick" 
gem "carrierwave" 
gem "fog" 

यहाँ दृश्य है

number_to_human_size = (bytes) -> 
    sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'] 
    i = parseInt(Math.floor(Math.log(bytes)/Math.log(1024))) 
    return Math.round(bytes/Math.pow(1024, i), 2) + ' ' + sizes[i] 

dropzone_hover = (e) -> 
    e.preventDefault() 
    $(this).addClass("dropzone-hover") 

dropzone_leave = (e) -> 
    e.preventDefault() 
    $(this).removeClass("dropzone-hover") 

jQuery -> 
    global_count = 0 
    seconds_to_process = 0 
    processing_factor = 5 # seconds to convert/process each uploaded file 

    $("#testimonial_image").hide() 

    dropzone = $("#dropzone") 

    dropzone.bind "click", (e) -> 
    $("#testimonial_image").click() 

    dropzone.bind("dragover", dropzone_hover) 
    dropzone.bind("dragleave", dropzone_leave) 
    dropzone.bind("drop", dropzone_leave) 

    $("#new_testimonial").data("global-count", "0") 

    $("#new_testimonial").fileupload 
    dropZone: $("#dropzone") 
    maxFileSize: 5000000 # 5 MB 
    dataType: "script" 

    add: (e, data) -> 
     file = data.files[0] 
     file.readable_size = number_to_human_size(file.size) 
     data.context = $(tmpl("template-upload", file).trim()) 
     $("#new_testimonial").append(data.context) 
     data.submit() 
     global_count += 1 

    progress: (e, data) -> 
     if data.context 
     progress = parseInt(data.loaded/data.total * 100, 10) 
     data.context.find(".bar").css("width", progress + "%") 
     data.context.find(".percentage").text(progress + "%") 

    submit: (e, data) -> 
     $("#mask").show() 
     $("#modal").center().show() 

    progressall: (e, data) -> 
     $("#global-upload-count").text(global_count) 
     global_progress = parseInt(data.loaded/data.total * 100, 10) 
     $("#global-progress-bar").css("width", global_progress + "%") 
     $("#global-progress-percentage").text(global_progress + "%") 

     if global_progress >= 100 
     seconds_to_process = global_count * processing_factor 
     $("#global-processing-count").text(seconds_to_process) 

     $("#global-processing").show() 

     timer = setInterval(-> 
      seconds_to_process = seconds_to_process - 1 
      $("#global-processing-count").text(seconds_to_process) 

      if seconds_to_process == 0 
      clearInterval(timer) 
      global_count = 0 
      seconds_to_process = 0 
      $("#modal, #mask").hide(0) 
     , 1000) 

प्रशंसापत्र मॉडल:

class Testimonial < ActiveRecord::Base 
    mount_uploader :image, ImageUploader 

    def display_name 
    if name.blank? 
     return "Testimonial #{self.id}" 
    else 
     return name 
    end 
    end 
end 
+2

इसका उपयोग करें: http://blueimp.github.com/jQuery-File-Upload/ – apneadiving

+0

@ एपनेडिविंग जो वास्तव में काम करता था कि मैं इसे कैसे चाहता था। प्लगइन पेज में कुछ बहुत उपयोगी उदाहरण थे जो मुझे सही दिशा में इंगित करते थे और मैंने जो भी चाहता हूं उसे लागू किया है। यदि आप किसी टिप्पणी के बजाय प्रश्न का उत्तर देते हैं, तो मैं खुशी से आपका जवाब स्वीकार करूंगा। बहुत बहुत धन्यवाद, आपने मुझे बहुत प्रयास करने में मदद की। –

+0

पढ़ने के लिए अच्छा :) – apneadiving

उत्तर

6

टिप्पणी में सलाह दी के रूप में, का उपयोग jQuery अपलोड: http://blueimp.github.com/jQuery-File-Upload/

+7

जबकि यह सैद्धांतिक रूप से प्रश्न का उत्तर दे सकता है, [यह बेहतर होगा] (http://meta.stackexchange.com/q/8259) यहां उत्तर के आवश्यक हिस्सों को शामिल करने के लिए, और संदर्भ के लिए लिंक प्रदान करें। –

+1

@IlmariKaronen मैंने प्रश्नकर्ता अनुरोध पर पोस्ट किया। लेकिन अगर आपको – apneadiving

+0

पसंद है तो डाउनवोट को बेझिझक महसूस करें किसी ने आपके उत्तर को "जवाब नहीं" के रूप में चिह्नित किया है। मैं काफी सहमत नहीं हूं, लेकिन यह * सुंदर सीमा रेखा है। उस ने कहा, सवाल बिल्कुल स्पष्ट नहीं है, या तो। –

0

मैंने इस कार्यक्षमता के लिए एक मूल पुस्तकालय लिखना शुरू कर दिया है। मेरे पास जिथब पर एक वर्किंग वर्जन है, और ब्लॉग पोस्ट की एक श्रृंखला लिख ​​रहा हूं ताकि यह विस्तार किया जा सके कि इसे कैसे प्राप्त किया जाए।

'वर्किंग' कोड: https://github.com/joeandrews/s3multipartupload पर पाया जा सकता है।

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