2010-10-23 26 views
77

के साथ HTML5 फ़ाइल अपलोड का उपयोग करना मान्य है, स्टैक ओवरफ़्लो पर आसपास के समान प्रश्न हैं, लेकिन ऐसा लगता है कि कोई भी मेरी आवश्यकताओं को पूरा नहीं करता है।AJAX और jQuery

यहाँ मैं क्या करने के लिए देख रहा हूँ है:

  • अपलोड डेटा की एक पूरी प्रपत्र, CodeIgniter के फाइल अपलोड पुस्तकालय के साथ एक एकल फ़ाइल
  • कार्य है एक टुकड़ा जिनमें से

यहां तक ​​कि सब ठीक है। डेटा को मेरे डेटाबेस में मिलता है क्योंकि मुझे इसकी आवश्यकता है। लेकिन मैं यह भी एक AJAX पोस्ट के माध्यम से मेरी प्रपत्र सबमिट करना चाहते हैं:

  • देशी एचटीएमएल 5 फ़ाइल एपीआई का उपयोग करना, फ्लैश या एक iframe समाधान
  • अधिमानतः निम्न स्तर .ajax() jQuery विधि के साथ इंटरफ़ेस नहीं

मुझे लगता है कि मैं कल्पना कर सकता हूं कि जब फ़ाइल का मूल्य शुद्ध जावास्क्रिप्ट का उपयोग करके बदलता है, तो फ़ाइल को स्वत: अपलोड करके इसे कैसे किया जाए, लेकिन मैं इसे सभी में करूँगा jQuery में सबमिट करने के लिए। मुझे लगता है कि क्वेरी स्ट्रिंग्स के माध्यम से करना संभव नहीं है क्योंकि मुझे पूरी फाइल ऑब्जेक्ट को पास करने की ज़रूरत है, लेकिन इस बिंदु पर मुझे क्या करना है, इस पर थोड़ा सा खो गया है।

क्या यह हासिल किया जा सकता है?

+0

मुझे कोडिनेटर भाग के बारे में कोई जानकारी नहीं है, लेकिन jQuery भाग के लिए, [इस प्लगइन] के लिए एक नज़र डालें] (http://code.google.com/p/jquery-html5-upload/)। – BalusC

+3

संबंधित: http://stackoverflow.com/questions/166221/how-can-i-upload-files-asynchronously-with-jquery –

उत्तर

85

यह बहुत कठिन नहीं है। सबसे पहले, FileReader Interface पर एक नज़र डालें।

तो, जब फ़ॉर्म सबमिट सबमिट करने की प्रक्रिया और

var file = document.getElementById('fileBox').files[0]; //Files[0] = 1st file 
var reader = new FileReader(); 
reader.readAsText(file, 'UTF-8'); 
reader.onload = shipOff; 
//reader.onloadstart = ... 
//reader.onprogress = ... <-- Allows you to update a progress bar. 
//reader.onabort = ... 
//reader.onerror = ... 
//reader.onloadend = ... 


function shipOff(event) { 
    var result = event.target.result; 
    var fileName = document.getElementById('fileBox').files[0].name; //Should be 'picture.jpg' 
    $.post('/myscript.php', { data: result, name: fileName }, continueSubmission); 
} 

फिर पकड़ने, सर्वर साइड (अर्थात myscript.php) पर:

$data = $_POST['data']; 
$fileName = $_POST['name']; 
$serverFile = time().$fileName; 
$fp = fopen('/uploads/'.$serverFile,'w'); //Prepends timestamp to prevent overwriting 
fwrite($fp, $data); 
fclose($fp); 
$returnData = array("serverFile" => $serverFile); 
echo json_encode($returnData); 

या कुछ ऐसा। मुझे गलत हो सकता है (और यदि मैं हूं, कृपया मुझे सही करें), लेकिन इस फ़ाइल को 1287916771myPicture.jpg जैसे /uploads/ में अपने सर्वर पर संग्रहीत करना चाहिए, और JSON चर के साथ प्रतिक्रिया दें (continueSubmission() फ़ंक्शन पर) जिसमें सर्वर पर फ़ाइल नाम है ।

fwrite() और jQuery.post() देखें।

ऊपर पेज यह विवरण readAsBinaryString(), readAsDataUrl(), और readAsArrayBuffer() अपने अन्य जरूरतों के लिए (जैसे चित्र, वीडियो, आदि) का उपयोग करने के लिए कैसे करें।

+0

हे क्लार्क, क्या मैं सही ढंग से समझ रहा हूं?यह अपलोड की गई फ़ाइल को फ़ाइल सिस्टम से फ़ाइल रीडर कन्स्ट्रक्टर में लोड होने के तुरंत बाद, jQuery के निम्न-स्तर .ajax हैंडलर को छोड़कर भेज देगा। फिर बाकी का फॉर्म सामान्य के रूप में जमा होगा? –

+0

ठीक है, इसलिए मैं पहले अपनी समझ में गलत था। अब मैं एक छवि के readAsDataUrl ले रहा हूं, इसे अपने डेटास्टिंग में .ajax में जोड़ रहा हूं, और मेरी सारी जानकारी एक साथ सबमिट कर रहा हूं। मेरे पिछले समाधान में कोडइग्निटर की डिफ़ॉल्ट फ़ाइल इनपुट क्लास शामिल थी जिसने $ _FILES ['field'] से डेटा पकड़ा था, इसलिए ऐसा लगता है कि मुझे बेस 64 छवि डेटा को पार्स करने के लिए एक अलग समाधान पर स्विच करने की आवश्यकता होगी। उस पर किसी भी सलाह का स्वागत है, यहां अपना जवाब ऊपर उठाना, और एक बार जब मैं कार्यान्वयन पूरा कर लेता हूं, तो मैं इसे सही के रूप में चिह्नित करूंगा। –

+1

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

6
jQuery (और FormData एपीआई) के बिना आप कुछ इस तरह उपयोग कर सकते हैं के साथ

:

function readFile(file){ 
    var loader = new FileReader(); 
    var def = $.Deferred(), promise = def.promise(); 

    //--- provide classic deferred interface 
    loader.onload = function (e) { def.resolve(e.target.result); }; 
    loader.onprogress = loader.onloadstart = function (e) { def.notify(e); }; 
    loader.onerror = loader.onabort = function (e) { def.reject(e); }; 
    promise.abort = function() { return loader.abort.apply(loader, arguments); }; 

    loader.readAsBinaryString(file); 

    return promise; 
} 

function upload(url, data){ 
    var def = $.Deferred(), promise = def.promise(); 
    var mul = buildMultipart(data); 
    var req = $.ajax({ 
     url: url, 
     data: mul.data, 
     processData: false, 
     type: "post", 
     async: true, 
     contentType: "multipart/form-data; boundary="+mul.bound, 
     xhr: function() { 
      var xhr = jQuery.ajaxSettings.xhr(); 
      if (xhr.upload) { 

       xhr.upload.addEventListener('progress', function(event) { 
        var percent = 0; 
        var position = event.loaded || event.position; /*event.position is deprecated*/ 
        var total = event.total; 
        if (event.lengthComputable) { 
         percent = Math.ceil(position/total * 100); 
         def.notify(percent); 
        }      
       }, false); 
      } 
      return xhr; 
     } 
    }); 
    req.done(function(){ def.resolve.apply(def, arguments); }) 
     .fail(function(){ def.reject.apply(def, arguments); }); 

    promise.abort = function(){ return req.abort.apply(req, arguments); } 

    return promise; 
} 

var buildMultipart = function(data){ 
    var key, crunks = [], bound = false; 
    while (!bound) { 
     bound = $.md5 ? $.md5(new Date().valueOf()) : (new Date().valueOf()); 
     for (key in data) if (~data[key].indexOf(bound)) { bound = false; continue; } 
    } 

    for (var key = 0, l = data.length; key < l; key++){ 
     if (typeof(data[key].value) !== "string") { 
      crunks.push("--"+bound+"\r\n"+ 
       "Content-Disposition: form-data; name=\""+data[key].name+"\"; filename=\""+data[key].value[1]+"\"\r\n"+ 
       "Content-Type: application/octet-stream\r\n"+ 
       "Content-Transfer-Encoding: binary\r\n\r\n"+ 
       data[key].value[0]); 
     }else{ 
      crunks.push("--"+bound+"\r\n"+ 
       "Content-Disposition: form-data; name=\""+data[key].name+"\"\r\n\r\n"+ 
       data[key].value); 
     } 
    } 

    return { 
     bound: bound, 
     data: crunks.join("\r\n")+"\r\n--"+bound+"--" 
    }; 
}; 

//---------- 
//---------- On submit form: 
var form = $("form"); 
var $file = form.find("#file"); 
readFile($file[0].files[0]).done(function(fileData){ 
    var formData = form.find(":input:not('#file')").serializeArray(); 
    formData.file = [fileData, $file[0].files[0].name]; 
    upload(form.attr("action"), formData).done(function(){ alert("successfully uploaded!"); }); 
}); 
FormData API की मदद से

तुम सिर्फ FormData वस्तु अपने फ़ॉर्म के सभी क्षेत्रों को जोड़ने और $ .ajax के माध्यम से भेज करने के लिए है ({url: url, data: formData, processData: false, content टाइप: गलत, टाइप: "POST"})

+0

यह समाधान उस सीमा को संबोधित नहीं करता है जो XMLHttpRequest.send() इसके माध्यम से फ़नल किए गए डेटा पर लगाता है। जब एक स्ट्रिंग पारित की जाती है (जैसे आपका मल्टीपार्ट), भेजें() बाइनरी डेटा का समर्थन नहीं करता है। यहां आपके मल्टीपार्ट को यूटीएफ -8 स्ट्रिंग के रूप में माना जाएगा, और बाइनरी डेटा को चकित या दूषित करेगा जो मान्य utf-8 नहीं है। यदि आपको वास्तव में फॉर्मडाटा से बचने की आवश्यकता है, तो आपको XMLHttpRequest.sendAsBinary() ([पॉलीफिल उपलब्ध] (https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#sendAsBinary()) का उपयोग करने की आवश्यकता है। दुर्भाग्यवश इसका मतलब है कि AJAX कॉल के लिए jQuery का उपयोग करना अधिक कठिन हो जाता है। –