javascript - मैं फ़ाइलों को असंकालिक रूप से कैसे अपलोड कर सकता हूं?




jquery ajax asynchronous upload (25)

मुझे मिला एक समाधान <form> एक छुपा iFrame को लक्षित <form> था। IFrame तब उपयोगकर्ता को प्रदर्शित करने के लिए जेएस चला सकता है कि यह पूर्ण हो गया है (पृष्ठ लोड पर)।

मैं jQuery के साथ असीमित रूप से एक फ़ाइल अपलोड करना चाहता हूं। यह मेरा एचटीएमएल है:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

और यहां मेरा Jquery कोड:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

फ़ाइल अपलोड होने के बजाय, मुझे केवल फ़ाइल नाम मिल रहा है। इस समस्या को सुलझाने में मैं क्या कर सकता हूं?

वर्तमान समाधान

मैं फ़ाइलों को अपलोड करने के लिए jQuery फॉर्म प्लगइन का उपयोग कर रहा हूँ।


फ़ाइल अपलोड करने का तरीका केवल एक और समाधान है ( बिना किसी प्लगइन के )

सरल जावास्क्रिप्ट और AJAX का उपयोग करना (प्रगति-बार के साथ)

एचटीएमएल भाग

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

जेएस भाग

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

PHP भाग

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

यहां उदाहरण आवेदन है


2017 अद्यतन: यह अभी भी आपके जनसांख्यिकीय उपयोग के ब्राउज़र पर निर्भर करता है।

"नई" एचटीएमएल 5 file एपीआई के साथ समझने के लिए एक महत्वपूर्ण बात यह है कि आईई 10 तक समर्थित नहीं है । यदि आपके द्वारा लक्षित विशिष्ट बाजार में विंडोज के पुराने संस्करणों की तुलना में औसत से अधिक औसतता है, तो हो सकता है कि आपके पास इसका उपयोग न हो।

2017 में जाकर, लगभग 5% ब्राउज़र आईई 6, 7, 8 या 9 में से एक हैं। यदि आप एक बड़े निगम में जाते हैं (उदाहरण के लिए यह एक बी 2 बी उपकरण है, या जो कुछ आप प्रशिक्षण के लिए दे रहे हैं) तो वह संख्या रॉकेट हो सकती है। कुछ महीने पहले - 2016 में- मैंने अपनी मशीनों की 60% से अधिक आईई 8 का उपयोग कर कंपनी के साथ निपटाया।

तो इससे पहले कि आप कुछ भी करें: जांचें कि आपके उपयोगकर्ता किस ब्राउजर का उपयोग करते हैं । यदि आप नहीं करते हैं, तो आप "मेरे लिए काम करता है" में एक त्वरित और दर्दनाक सबक सीखेंगे, जो किसी ग्राहक को देने योग्य नहीं है।

2008 से मेरा जवाब निम्नानुसार है।

हालांकि, फाइल अपलोड के व्यवहार्य गैर-जेएस विधियां हैं। आप पृष्ठ पर एक आईफ्रेम बना सकते हैं (जिसे आप सीएसएस के साथ छिपाते हैं) और फिर उस फॉर्म को पोस्ट करने के लिए अपने फॉर्म को लक्षित करें। मुख्य पृष्ठ को स्थानांतरित करने की आवश्यकता नहीं है।

यह एक "वास्तविक" पोस्ट है, इसलिए यह पूरी तरह से इंटरैक्टिव नहीं है। यदि आपको स्थिति की आवश्यकता है तो आपको प्रक्रिया करने के लिए कुछ सर्वर-साइड की आवश्यकता है। यह आपके सर्वर के आधार पर बड़े पैमाने पर भिन्न होता है। ASP.NET में अच्छे तंत्र हैं। PHP सादा विफल रहता है, लेकिन आप इसके आसपास पाने के लिए Perl या अपाचे संशोधनों का उपयोग कर सकते हैं।

यदि आपको एकाधिक फ़ाइल-अपलोड की आवश्यकता है, तो प्रत्येक फ़ाइल को एक बार में करना सर्वोत्तम है (अधिकतम फ़ाइल अपलोड सीमाओं को पार करने के लिए)। आईफ्रेम पर पहला फॉर्म पोस्ट करें, उपरोक्त का उपयोग करके इसकी प्रगति की निगरानी करें और जब यह समाप्त हो जाए, तो दूसरा फॉर्म iframe पर पोस्ट करें, और इसी तरह।

या जावा / फ्लैश समाधान का उपयोग करें। वे अपनी पोस्ट के साथ क्या कर सकते हैं में बहुत अधिक लचीला हैं ...


एचटीएमएल 5 और जावास्क्रिप्ट का उपयोग करना , एसिंक अपलोड करना काफी आसान है, मैं आपके एचटीएमएल के साथ अपलोडिंग तर्क बना देता हूं, यह पूरी तरह काम नहीं कर रहा है क्योंकि इसे एपीआई की जरूरत है, लेकिन यह दिखाएं कि यह कैसे काम करता है, अगर आपके पास /uploadअपनी वेबसाइट की जड़ से अंतराल बिंदु है , यह कोड आपके लिए काम करना चाहिए:

const asyncFileUpload = () => {
  const fileInput = document.getElementById("file");
  const file = fileInput.files[0];
  const uri = "/upload";
  const xhr = new XMLHttpRequest();
  xhr.upload.onprogress = e => {
    const percentage = e.loaded / e.total;
    console.log(percentage);
  };
  xhr.onreadystatechange = e => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log("file uploaded");
    }
  };
  xhr.open("POST", uri, true);
  xhr.setRequestHeader("X-FileName", file.name);
  xhr.send(file);
}
<form>
  <span>File</span>
  <input type="file" id="file" name="file" size="10" />
  <input onclick="asyncFileUpload()" id="upload" type="button" value="Upload" />
</form>

XMLHttpReques के बारे में कुछ और जानकारी:

XMLHttpRequest ऑब्जेक्ट

सभी आधुनिक ब्राउज़र XMLHttpRequest ऑब्जेक्ट का समर्थन करते हैं। XMLHttpRequest ऑब्जेक्ट का उपयोग दृश्यों के पीछे एक वेब सर्वर के साथ डेटा का आदान-प्रदान करने के लिए किया जा सकता है। इसका मतलब है कि पूरे पृष्ठ को पुनः लोड किए बिना, किसी वेब पेज के हिस्सों को अपडेट करना संभव है।


एक XMLHttpRequest ऑब्जेक्ट बनाएँ

सभी आधुनिक ब्राउज़रों (क्रोम, फ़ायरफ़ॉक्स, आई 7 +, एज, सफारी, ओपेरा) में अंतर्निहित XMLHttpRequest ऑब्जेक्ट है।

XMLHttpRequest ऑब्जेक्ट बनाने के लिए सिंटेक्स:

परिवर्तनीय = नया XMLHttpRequest ();


डोमेन भर में प्रवेश करें

सुरक्षा कारणों से, आधुनिक ब्राउज़र डोमेन पर पहुंच की अनुमति नहीं देते हैं।

इसका मतलब यह है कि वेब पेज और एक्सएमएल फ़ाइल दोनों लोड करने का प्रयास करते हैं, उसी सर्वर पर स्थित होना चाहिए।

W3Schools पर उदाहरण W3Schools डोमेन पर स्थित सभी खुली एक्सएमएल फाइलें।

यदि आप ऊपर दिए गए उदाहरण का उपयोग अपने स्वयं के वेब पृष्ठों पर करना चाहते हैं, तो आपके द्वारा लोड की जाने वाली एक्सएमएल फाइलें आपके सर्वर पर स्थित होनी चाहिए।

अधिक जानकारी के लिए, आप here पढ़ना जारी रख सकते here ...


आप जावास्क्रिप्ट या jQuery का उपयोग करके असीमित एकाधिक फ़ाइल अपलोड कर सकते हैं और किसी भी प्लगइन का उपयोग किए बिना। आप प्रगति नियंत्रण में फ़ाइल अपलोड की वास्तविक समय प्रगति भी दिखा सकते हैं। मैं 2 अच्छे लिंक में आया हूँ -

  1. प्रगति पट्टी के साथ एएसपी.नेट वेब फॉर्म आधारित Mulitple फ़ाइल अपलोड फ़ीचर
  2. JQuery में किए गए एएसपी.नेट एमवीसी आधारित एकाधिक फ़ाइल अपलोड

सर्वर साइड भाषा सी # है लेकिन आप PHP जैसे अन्य भाषा के साथ काम करने के लिए कुछ संशोधन कर सकते हैं।

फाइल अपलोड एएसपी.नेट कोर एमवीसी:

दृश्य में एचटीएमएल में फ़ाइल अपलोड नियंत्रण बनाएँ:

[HttpPost]
public async Task<IActionResult> Add(IFormFile[] mediaUpload)
{
    //looping through all the files
    foreach (IFormFile file in mediaUpload)
    {
        //saving the files
        string path = Path.Combine(hostingEnvironment.WebRootPath, "some-folder-path"); 
        using (var stream = new FileStream(path, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }
}

अब अपने नियंत्रक में एक्शन विधि बनाएं:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}

hostingEnvironment variable प्रकार IHostingEnvironment प्रकार है जिसे निर्भरता इंजेक्शन का उपयोग कर नियंत्रक को इंजेक्शन दिया जा सकता है, जैसे:

$('#fileupload').fileupload({
    add: function (e, data) {
        var that = this;
        $.getJSON('/example/url', function (result) {
            data.formData = result; // e.g. {id: 123}
            $.blueimp.fileupload.prototype
                .options.add.call(that, e, data);
        });
    } 
});

मैं छवियों को अपलोड करने के लिए नीचे दी गई स्क्रिप्ट का उपयोग कर रहा हूं जो ठीक काम करने के लिए होता है।

एचटीएमएल

<input id="file" type="file" name="file"/>
<div id="response"></div>

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

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

व्याख्या

मैं अपलोडिंग एनीमेशन दिखाने के लिए प्रतिक्रिया div का उपयोग करता हूं और अपलोड करने के बाद प्रतिक्रिया देता हूं।

सबसे अच्छा हिस्सा यह है कि आप इस स्क्रिप्ट का उपयोग करते समय फ़ाइल के साथ अतिरिक्त डेटा जैसे आईडी और आदि भेज सकते हैं। मैंने स्क्रिप्ट में extra-data उल्लेख किया है।

PHP स्तर पर यह सामान्य फ़ाइल अपलोड के रूप में काम करेगा। अतिरिक्त डेटा $_POST डेटा के रूप में पुनर्प्राप्त किया जा सकता है।

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


Jquery के बिना एक आधुनिक दृष्टिकोण FileList ऑब्जेक्ट का उपयोग करना है <input type="file">जब आप किसी फ़ाइल को चुनते हैं और फिर FormData ऑब्जेक्ट के चारों ओर लिपटे FormData को पोस्ट करने के लिए Fetch करें ।FormData

// The input DOM element
const inputElement = document.querySelector('input');

// Listen for a file submit from user
inputElement.addEventListener('change', () => {
    const data = new FormData()
    data.append('file', inputElement.files[0])
    data.append('imageName', 'flower')

    // Post to server
    fetch('/uploadImage', {
        method: 'POST',
        body: data
    })
});

मैं इस उद्देश्य के लिए ठीक अपलोडर प्लगइन का उपयोग करने की सलाह देते हैं। आपका JavaScript कोड होगा:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

Jquery के साथ फ़ाइल को अतुल्यकालिक रूप से अपलोड करने के लिए नीचे दिए गए चरणों का उपयोग करें:

चरण 1 अपनी प्रोजेक्ट में Nuget प्रबंधक खोलें और पैकेज जोड़ें (jquery fileupload (केवल आपको इसे खोज बॉक्स में लिखना होगा, यह आ जाएगा और इसे इंस्टॉल करेगा।)) यूआरएल: https://github.com/blueimp/jQuery-File- अपलोड

चरण 2 HTML फ़ाइलों में स्क्रिप्ट्स को नीचे जोड़ें, जो उपरोक्त पैकेज चलाकर प्रोजेक्ट में पहले ही जोड़े गए हैं:

jquery.ui.widget.js

jquery.iframe-transport.js

jquery.fileupload.js

चरण 3 नीचे कोड के अनुसार फ़ाइल अपलोड नियंत्रण लिखें:

<input id="upload" name="upload" type="file" />

चरण 4 अपलोड के रूप में एक जेएस विधि लिखें नीचे के रूप में फ़ाइल:

 function uploadFile(element) {

            $(element).fileupload({

                dataType: 'json',
                url: '../DocumentUpload/upload',
                autoUpload: true,
                add: function (e, data) {           
                  // write code for implementing, while selecting a file. 
                  // data represents the file data. 
                  //below code triggers the action in mvc controller
                  data.formData =
                                    {
                                     files: data.files[0]
                                    };
                  data.submit();
                },
                done: function (e, data) {          
                   // after file uploaded
                },
                progress: function (e, data) {

                   // progress
                },
                fail: function (e, data) {

                   //fail operation
                },
                stop: function () {

                  code for cancel operation
                }
            });

        };

चरण 5 तैयार फ़ंक्शन कॉल तत्व फ़ाइल में नीचे प्रक्रिया के अनुसार प्रक्रिया शुरू करने के लिए अपलोड करें:

$(document).ready(function()
{
    uploadFile($('#upload'));

});

चरण 6 नीचे के अनुसार एमवीसी नियंत्रक और कार्रवाई लिखें:

public class DocumentUploadController : Controller
    {       

        [System.Web.Mvc.HttpPost]
        public JsonResult upload(ICollection<HttpPostedFileBase> files)
        {
            bool result = false;

            if (files != null || files.Count > 0)
            {
                try
                {
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file.ContentLength == 0)
                            throw new Exception("Zero length file!");                       
                        else 
                            //code for saving a file

                    }
                }
                catch (Exception)
                {
                    result = false;
                }
            }


            return new JsonResult()
                {
                    Data=result
                };


        }

    }

jQuery Uploadify एक और अच्छी प्लगइन है जिसे मैंने फ़ाइलों को अपलोड करने से पहले उपयोग किया है। जावास्क्रिप्ट कोड निम्न के रूप में सरल है: कोड। हालांकि, नया संस्करण इंटरनेट एक्सप्लोरर में काम नहीं करता है।

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

मैंने बहुत सारी खोज की है और मैं बिना किसी प्लगइन के फाइलों को अपलोड करने और केवल अजाक्स के साथ एक और समाधान में आया हूं। समाधान नीचे जैसा है:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}

आप XMLHttpRequest (फ्लैश और आईफ्रेम निर्भरता के बिना) का उपयोग करके एसिंक्रोनस अपलोड करने पर फ़ाइल नाम के साथ अतिरिक्त पैरामीटर पास कर सकते हैं। फॉर्मडाटा के साथ अतिरिक्त पैरामीटर मान संलग्न करें और अपलोड अनुरोध भेजें।

function uploadButtonCLicked(){
    var input = document.querySelector('input[type="file"]')

    fetch('/url', {
      method: 'POST',
      body: input.files[0]
    }).then(res => res.json())   // you can do something with response
      .catch(error => console.error('Error:', error))
      .then(response => console.log('Success:', response));
}                               

साथ ही, सिंकफ्यूजन जावास्क्रिप्ट यूआई फ़ाइल अपलोड घटना परिदृश्य का उपयोग करके इस परिदृश्य के लिए समाधान प्रदान करता है। आप यहां इस दस्तावेज़ के बारे में दस्तावेज और इस बारे में अधिक जानकारी प्राप्त कर सकते हैं यहां लिंक विवरण दर्ज करें


मैंने इसे रेल पर्यावरण में लिखा है । यदि आप लाइटवेट jQuery-form प्लगइन का उपयोग करते हैं, तो यह केवल जावास्क्रिप्ट की लगभग पांच पंक्तियां है।

चुनौती AJAX अपलोड को मानक remote_form_for रूप में काम करने में है, बहु-भाग फ़ॉर्म सबमिशन को समझ में नहीं आता है। यह फ़ाइल डेटा भेजने वाला नहीं है रेल्स AJAX अनुरोध के साथ वापस मांगता है।

यही वह जगह है जहां jQuery-form प्लगइन खेल में आता है।

इसके लिए रेल कोड यहां दिया गया है:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

यहां संबंधित जावास्क्रिप्ट है:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

और यहां रेल नियंत्रक कार्रवाई है, सुंदर वेनिला:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

मैं ब्लॉगजीटी के साथ पिछले कुछ हफ्तों के लिए इसका उपयोग कर रहा हूं, और यह एक चैंप की तरह काम करता है।


नोट: यह उत्तर पुराना है, अब एक्सएचआर का उपयोग कर फाइल अपलोड करना संभव है।

आप XMLHttpRequest (अजाक्स) का उपयोग कर फ़ाइलों को अपलोड नहीं कर सकते हैं। आप एक आईफ्रेम या फ्लैश का उपयोग कर प्रभाव अनुकरण कर सकते हैं। उत्कृष्ट jQuery फॉर्म प्लगइन जो प्रभाव प्राप्त करने के लिए आईफ्रेम के माध्यम से आपकी फ़ाइलों को पोस्ट करता है।


यह AJAX फ़ाइल अपलोड jQuery प्लगइन फ़ाइल को कुछ अपलोड करता है, और कॉलबैक के जवाब को पास करता है, और कुछ नहीं।

  • यह विशिष्ट HTML पर निर्भर नहीं है, बस इसे एक <input type="file">
  • यह किसी भी विशेष तरीके से आपके सर्वर को जवाब देने की आवश्यकता नहीं है
  • इससे कोई फर्क नहीं पड़ता कि आप कितनी फाइलों का उपयोग करते हैं, या वे पृष्ठ पर कहां हैं

- जितना कम उपयोग करें -

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

- या जितना -

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});

भविष्य के पाठकों के लिए लपेटना।

असीमित फ़ाइल अपलोड करें

एचटीएमएल 5 के साथ

FormData और फ़ाइल एपीआई समर्थित हैं (दोनों HTML5 फीचर्स) यदि आप $.ajax() FormData $.ajax() विधि का उपयोग कर jQuery के साथ फ़ाइलों को अपलोड कर सकते हैं।

आप फॉर्मडाटा के बिना भी फाइलें भेज सकते हैं लेकिन फ़ाइलों को संसाधित करने के लिए फ़ाइल एपीआई मौजूद होना चाहिए ताकि उन्हें XMLHttpRequest (Ajax) के साथ भेजा जा सके।

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

एक त्वरित, शुद्ध जावास्क्रिप्ट ( कोई jQuery ) उदाहरण के लिए " फ़ॉर्मडाटा ऑब्जेक्ट का उपयोग करके फ़ाइलों को भेजना " देखें।

मैदान छोड़ना

जब एचटीएमएल 5 समर्थित नहीं है (कोई फ़ाइल एपीआई ) एकमात्र अन्य शुद्ध जावास्क्रिप्ट समाधान (कोई फ्लैश या कोई अन्य ब्राउज़र प्लगइन) छिपी आईफ्रेम तकनीक है, जो XMLHttpRequest ऑब्जेक्ट का उपयोग किए बिना एक एसिंक्रोनस अनुरोध को अनुकरण करने की अनुमति देता है।

इसमें फ़ाइल इनपुट के साथ फॉर्म के लक्ष्य के रूप में एक आईफ्रेम सेट करना शामिल है। जब उपयोगकर्ता अनुरोध सबमिट करता है और फ़ाइलों को अपलोड किया जाता है लेकिन प्रतिक्रिया मुख्य पृष्ठ को पुन: प्रस्तुत करने के बजाय iframe के अंदर प्रदर्शित होती है। आईफ्रेम छिपाने से पूरी प्रक्रिया उपयोगकर्ता को पारदर्शी बनाती है और एक एसिंक्रोनस अनुरोध को अनुकरण करती है।

अगर सही तरीके से किया जाता है तो इसे किसी भी ब्राउज़र पर वर्चुअल रूप से काम करना चाहिए, लेकिन इसमें कुछ चेतावनी हैं जैसे आईफ्रेम से प्रतिक्रिया प्राप्त करने के लिए।

इस मामले में आप एक रैपर प्लगइन का उपयोग करना पसंद कर सकते हैं जैसे Bifröst जो आईफ्रेम तकनीक का उपयोग करता है लेकिन एक jQuery अजाक्स परिवहन भी प्रदान करता है जो फ़ाइलों को केवल $.ajax() विधि के साथ भेजने की इजाजत देता है:

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

प्लगइन्स

Bifröst सिर्फ एक छोटा सा आवरण है जो jQuery की AJAX विधि में फ़ॉलबैक समर्थन जोड़ता है, लेकिन jQuery फॉर्म प्लगइन या jQuery फ़ाइल अपलोड जैसे उपरोक्त कई प्लगइन में HTML5 से अलग फ़ॉलबैक और प्रक्रिया को कम करने के लिए कुछ उपयोगी सुविधाएं शामिल हैं। आपकी जरूरतों और आवश्यकताओं के आधार पर आप एक नंगे कार्यान्वयन या इनमें से किसी भी प्लगइन पर विचार करना चाहेंगे।


यह मेरा समाधान है।

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

और जेएस

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

नियंत्रक

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    return Json(":)");
}

फ़ाइल के लिए अपलोड प्रक्रिया को संभालने की तलाश करें, यहां पर अतुल्यकालिक रूप से: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

लिंक से नमूना

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>

आप बस jQuery .ajax() साथ अपलोड कर सकते हैं।

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

सीएसएस

.progress { display: none; }

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

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});

JQuery के लिए फ़ाइल अपलोड करने पर कई तैयार किए गए प्लगइन हैं।

इस तरह के अपलोडिंग हैक्स करना एक सुखद अनुभव नहीं है, इसलिए लोग तैयार किए गए समाधानों का उपयोग करके आनंद लेते हैं।

यहां कुछ हैं:

आप एनपीएम पर अधिक परियोजनाओं की खोज कर सकते हैं (कीवर्ड के रूप में "jquery-plugin" का उपयोग करके) या गिथब पर।


मैं कुछ वास्तव में शक्तिशाली jQuery- आधारित फ़ाइल अपलोड पुस्तकालयों में आया हूँ। इन्हें जांचें:

  1. Plupload
  2. jQuery फ़ाइल अपलोड करें
    • दस्तावेज़: https://github.com/blueimp/jQuery- फ़ाइल- अपलोड करें
  3. fineuploader.com

var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

आप छवियों सहित अपने सभी मूल्यों को पोस्ट करने के लिए फॉर्म डेटा का उपयोग कर सकते हैं।


आप इसे आसानी से वेनिला जावास्क्रिप्ट में कर सकते हैं। मेरे वर्तमान प्रोजेक्ट से स्निपेट यहां दिया गया है:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);

अतीत में मैंने सबसे सरल और सबसे मजबूत तरीका यह किया है, बस अपने फॉर्म के साथ एक छिपी आईफ्रेम टैग को लक्षित करना है - फिर यह पेज को पुनः लोड किए बिना iframe के भीतर सबमिट करेगा।

ऐसा है कि आप एचटीएमएल के अलावा प्लगइन, जावास्क्रिप्ट या "जादू" के किसी अन्य रूप का उपयोग नहीं करना चाहते हैं। बेशक आप जावास्क्रिप्ट के साथ इसे जोड़ सकते हैं या आप क्या कर सकते हैं ...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

आप सर्वर त्रुटियों या सफलता प्रतिक्रियाओं के लिए iframe onLoad की सामग्री भी पढ़ सकते हैं और उसके बाद उपयोगकर्ता को आउटपुट कर सकते हैं।

क्रोम, iFrames, और ऑनलोड

-नोट- यदि आप अपलोड / डाउनलोड करते समय यूआई अवरोधक को सेटअप करने में रुचि रखते हैं तो आपको केवल पढ़ने की आवश्यकता है

वर्तमान में क्रोम फ़ाइलों को स्थानांतरित करने के लिए उपयोग किए जाने पर iframe के लिए ऑनलोड ईवेंट ट्रिगर नहीं करता है। फ़ायरफ़ॉक्स, आईई, और एज सभी फ़ाइल स्थानांतरण के लिए अधिभार घटना आग।

क्रोम के लिए काम करने वाला एकमात्र समाधान कुकी का उपयोग करना था।

मूल रूप से जब अपलोड / डाउनलोड शुरू होता है:

  • [क्लाइंट साइड] एक कुकी के अस्तित्व को देखने के लिए अंतराल शुरू करें
  • [सर्वर साइड] जो कुछ भी आपको फ़ाइल डेटा के साथ करना है
  • [सर्वर साइड] क्लाइंट साइड अंतराल के लिए कुकी सेट करें
  • [क्लाइंट साइड] अंतराल कुकी को देखता है और इसे ऑनलोड ईवेंट की तरह उपयोग करता है। उदाहरण के लिए आप यूआई अवरोधक शुरू कर सकते हैं और फिर ऑनलोड (या जब कुकी बनाई जाती है) आप यूआई अवरोधक को हटा सकते हैं।

इसके लिए एक कुकी का उपयोग बदसूरत है लेकिन यह काम करता है।

डाउनलोड करते समय क्रोम के लिए इस समस्या को संभालने के लिए मैंने एक jQuery प्लगइन बनाया है, आप यहां पा सकते हैं

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js

एक ही बुनियादी प्रिंसिपल अपलोड करने पर भी लागू होता है।

डाउनलोडर का उपयोग करने के लिए (जेएस शामिल करें, जाहिर है)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

और सर्वर की ओर, फ़ाइल डेटा स्थानांतरित करने से पहले, कुकी बनाएं

 setcookie('iDownloader', true, time() + 30, "/");

प्लगइन कुकी दिखाई देगी, और उसके बाद पूर्ण कॉलबैक ट्रिगर करें।


HTML5 साथ आप अजाक्स और jQuery के साथ फाइल अपलोड कर सकते हैं। इतना ही नहीं, आप फ़ाइल सत्यापन (नाम, आकार, और एमआईएमई प्रकार) कर सकते हैं या एचटीएमएल 5 प्रगति टैग (या एक div) के साथ प्रगति घटना को संभाल सकते हैं। हाल ही में मुझे एक फाइल अपलोडर बनाना पड़ा, लेकिन मैं Flash और इफ्रेम या प्लगइन्स का उपयोग नहीं करना चाहता था और कुछ शोध के बाद मैं समाधान के साथ आया था।

एचटीएमएल:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

सबसे पहले, यदि आप चाहें तो आप कुछ सत्यापन कर सकते हैं। उदाहरण के लिए, फ़ाइल की ऑन चेंज घटना में:

$(':file').on('change', function() {
    var file = this.files[0];
    if (file.size > 1024) {
        alert('max upload size is 1k')
    }

    // Also see .name, .type
});

अब अजाक्स बटन के क्लिक के साथ जमा करें:

$(':button').on('click', function() {
    $.ajax({
        // Your server script to process the upload
        url: 'upload.php',
        type: 'POST',

        // Form data
        data: new FormData($('form')[0]),

        // Tell jQuery not to process data or worry about content-type
        // You *must* include these options!
        cache: false,
        contentType: false,
        processData: false,

        // Custom XMLHttpRequest
        xhr: function() {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) {
                // For handling the progress of the upload
                myXhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        $('progress').attr({
                            value: e.loaded,
                            max: e.total,
                        });
                    }
                } , false);
            }
            return myXhr;
        }
    });
});

जैसा कि आप देख सकते हैं, HTML5 (और कुछ शोध) फ़ाइल अपलोडिंग के साथ न केवल संभव हो सकता है लेकिन सुपर आसान है। इसे Google क्रोम के साथ आज़माएं क्योंकि उदाहरण के कुछ HTML5 घटक प्रत्येक ब्राउज़र में उपलब्ध नहीं हैं।


शुरुआती के लिए जावास्क्रिप्ट बंद

मॉरिस ऑन ट्यू द्वारा प्रस्तुत, 2006-02-21 10:19। तब से समुदाय-संपादित।

बंद जादू नहीं हैं

यह पृष्ठ बंद करने की व्याख्या करता है ताकि एक प्रोग्रामर उन्हें समझ सके - वर्किंग जावास्क्रिप्ट कोड का उपयोग कर। यह गुरु या कार्यात्मक प्रोग्रामर के लिए नहीं है।

मूल अवधारणा को गले लगाने के बाद क्लोजर को समझना मुश्किल नहीं होता है। हालांकि, किसी भी सैद्धांतिक या अकादमिक उन्मुख स्पष्टीकरण पढ़कर उन्हें समझना असंभव है!

यह आलेख प्रोग्रामर के लिए मुख्यधारा की भाषा में कुछ प्रोग्रामिंग अनुभव के साथ है, और निम्न जावास्क्रिप्ट फ़ंक्शन को कौन पढ़ सकता है:

function sayHello(name) {
  var text = 'Hello ' + name;
  var say = function() { console.log(text); }
  say();
}
sayHello('Joe');

दो संक्षिप्त सारांश

  • जब कोई फ़ंक्शन (foo) अन्य फ़ंक्शंस (बार और बाज़) घोषित करता है, तो फ़ंक्शन में बनाए गए स्थानीय चर के परिवार को समाप्त होने पर नष्ट नहीं किया जाता है। चर केवल बाहरी दुनिया के लिए अदृश्य हो जाते हैं। इसलिए फू फ़ंक्शन बार और बाज़ को चालाकी से वापस कर सकता है, और वे चर के इस बंद-बंद परिवार ("बंद") के माध्यम से एक-दूसरे के साथ पढ़ना, लिखना और संवाद करना जारी रख सकते हैं, जो कि किसी और के साथ दखल नहीं दे सकता है, यहां तक ​​कि कोई भी जो कॉल नहीं करता भविष्य में फिर से foo।

  • एक बंद करना प्रथम श्रेणी के कार्यों का समर्थन करने का एक तरीका है; यह एक अभिव्यक्ति है जो इसके दायरे के भीतर चर का संदर्भ दे सकती है (जब इसे पहली बार घोषित किया गया था), एक चर को असाइन किया जाना चाहिए, किसी फ़ंक्शन के लिए तर्क के रूप में पारित किया जाना चाहिए, या फ़ंक्शन परिणाम के रूप में वापस किया जाना चाहिए।

बंद करने का एक उदाहरण

निम्न कोड किसी फ़ंक्शन का संदर्भ देता है:

function sayHello2(name) {
  var text = 'Hello ' + name; // Local variable
  var say = function() { console.log(text); }
  return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"

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

किसी फ़ंक्शन में सी पॉइंटर और फ़ंक्शन के लिए जावास्क्रिप्ट संदर्भ के बीच एक महत्वपूर्ण अंतर है। जावास्क्रिप्ट में, आप फंक्शन रेफरेंस वैरिएबल के बारे में सोच सकते हैं क्योंकि एक फंक्शन के लिए पॉइंटर और एक बंद करने के लिए एक छिपे हुए पॉइंटर के रूप में।

उपरोक्त कोड में एक बंद है क्योंकि अज्ञात फ़ंक्शन function() { console.log(text); } function() { console.log(text); } को एक और समारोह के अंदर घोषित किया गया है, इस उदाहरण में sayHello2() । जावास्क्रिप्ट में, यदि आप किसी अन्य फ़ंक्शन के अंदर function कीवर्ड का उपयोग करते हैं, तो आप एक बंद कर रहे हैं।

सी और अन्य सामान्य भाषाओं में, फ़ंक्शन रिटर्न के बाद , सभी स्थानीय चर अब उपलब्ध नहीं हैं क्योंकि स्टैक-फ्रेम नष्ट हो जाता है।

जावास्क्रिप्ट में, यदि आप किसी अन्य फ़ंक्शन के भीतर फ़ंक्शन घोषित करते हैं, तो बाहरी फ़ंक्शन के स्थानीय चर इसके से लौटने के बाद पहुंच योग्य रह सकते हैं। यह उपरोक्त प्रदर्शित किया गया है, क्योंकि हम कहने के बाद कहते हैं कि हम कहते हैं कि say2() से वापस आ गया है। ध्यान दें कि जिस कोड को हम कॉल करते हैं वह वेरिएबल text संदर्भ देता है, जो फ़ंक्शन का स्थानीय चर था, sayHello2()

function() { console.log(text); } // Output of say2.toString();

say2.toString() के आउटपुट को देखते हुए, हम देख सकते हैं कि कोड वेरिएबल text को संदर्भित करता है। अज्ञात फ़ंक्शन text को संदर्भित कर सकता है जिसमें 'Hello Bob' मान होता है क्योंकि sayHello2() के स्थानीय चर को sayHello2() को बंद में गुप्त रूप से जिंदा रखा गया है।

प्रतिभा यह है कि जावास्क्रिप्ट में एक फ़ंक्शन संदर्भ में बंद होने वाले बंद होने का एक गुप्त संदर्भ भी होता है - इसी प्रकार प्रतिनिधि एक विधि सूचक और ऑब्जेक्ट का गुप्त संदर्भ कैसे होते हैं।

और ज्यादा उदाहरण

किसी कारण से, जब आप उनके बारे में पढ़ते हैं तो बंद होने में वास्तव में मुश्किल लगती है, लेकिन जब आप कुछ उदाहरण देखते हैं, तो यह स्पष्ट हो जाता है कि वे कैसे काम करते हैं (मुझे थोड़ी देर लग गई)। मैं उदाहरणों के माध्यम से सावधानी से काम करने की सलाह देता हूं जब तक कि आप समझें कि वे कैसे काम करते हैं। यदि आप पूरी तरह से समझने के बिना बंद करने का उपयोग करना शुरू करते हैं, तो आप जल्द ही कुछ अजीब बग बनायेंगे!

उदाहरण 3

यह उदाहरण दिखाता है कि स्थानीय चर की प्रतिलिपि बनाई गई नहीं है - उन्हें संदर्भ द्वारा रखा जाता है। ऐसा लगता है कि बाहरी कार्य मौजूद होने के बावजूद स्टैक-फ्रेम स्मृति में जीवित रहता है!

function say667() {
  // Local variable that ends up within closure
  var num = 42;
  var say = function() { console.log(num); }
  num++;
  return say;
}
var sayNumber = say667();
sayNumber(); // logs 43

उदाहरण 4

सभी तीन वैश्विक कार्यों में एक ही बंद होने का एक आम संदर्भ है क्योंकि वे सभी को setupSomeGlobals() करने के लिए एक ही कॉल के भीतर घोषित किया जाता है।

var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
  // Local variable that ends up within closure
  var num = 42;
  // Store some references to functions as global variables
  gLogNumber = function() { console.log(num); }
  gIncreaseNumber = function() { num++; }
  gSetNumber = function(x) { num = x; }
}

setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); // 43
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;

setupSomeGlobals();
gLogNumber(); // 42

oldLog() // 5

तीन कार्यों को एक ही बंद करने के लिए साझा किया गया है - setupSomeGlobals() के स्थानीय चर setupSomeGlobals() जब तीन कार्यों को परिभाषित किया गया था।

ध्यान दें कि उपर्युक्त उदाहरण में, यदि आप setupSomeGlobals() फिर से कॉल करते हैं, तो एक नया बंद (स्टैक-फ्रेम!) बनाया गया है। पुराना gLogNumber , gIncreaseNumber , gSetNumber चर नए फ़ंक्शन के साथ नए कार्यों के साथ ओवरराइट किए जाते हैं। (जावास्क्रिप्ट में, जब भी आप किसी अन्य फ़ंक्शन के अंदर कोई फ़ंक्शन घोषित करते हैं, तो अंदरूनी फ़ंक्शन प्रत्येक बार बाहरी फ़ंक्शन कहलाता है / फिर से बनाया जाता है।)

उदाहरण 5

इस उदाहरण से पता चलता है कि बंद होने में बाहरी फ़ंक्शन के अंदर घोषित होने से पहले किसी स्थानीय चर को शामिल किया गया था। ध्यान दें कि परिवर्तनीय alice वास्तव में अज्ञात फ़ंक्शन के बाद घोषित किया जाता है। अज्ञात फ़ंक्शन को पहले घोषित किया जाता है, और जब उस फ़ंक्शन को कॉल किया जाता है तो यह alice वैरिएबल तक पहुंच सकता है क्योंकि alice एक ही दायरे में है (जावास्क्रिप्ट चर होस्टिंग है )। यह भी sayAlice()() बस सीधे sayAlice() से sayAlice() गए फ़ंक्शन संदर्भ को कॉल करता है - यह वही है जैसा पहले किया गया था लेकिन अस्थायी चर के बिना।

function sayAlice() {
    var say = function() { console.log(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return say;
}
sayAlice()();// logs "Hello Alice"

ट्रिकी: यह भी ध्यान रखें कि say चर भी बंद होने के अंदर है, और किसी भी अन्य फ़ंक्शन द्वारा एक्सेस किया जा सकता है जिसे sayAlice() भीतर घोषित किया जा सकता है, या इसे अंदर के फ़ंक्शन के भीतर रिकर्सिव रूप से एक्सेस किया जा सकता है।

उदाहरण 6

यह एक बहुत से लोगों के लिए एक वास्तविक गोचा है, इसलिए आपको इसे समझने की जरूरत है। सावधान रहें यदि आप लूप के भीतर किसी फ़ंक्शन को परिभाषित कर रहे हैं: बंद होने से स्थानीय चर कार्य नहीं कर सकते हैं जैसा कि आप पहले सोच सकते हैं।

इस उदाहरण को समझने के लिए आपको जावास्क्रिप्ट में "वेरिएबल होस्टिंग" सुविधा को समझने की आवश्यकता है।

function buildList(list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
        var item = 'item' + i;
        result.push( function() {console.log(item + ' ' + list[i])} );
    }
    return result;
}

function testList() {
    var fnlist = buildList([1,2,3]);
    // Using j only to help prevent confusion -- could use i.
    for (var j = 0; j < fnlist.length; j++) {
        fnlist[j]();
    }
}

 testList() //logs "item2 undefined" 3 times

लाइन result.push( function() {console.log(item + ' ' + list[i])} परिणाम सरणी में तीन बार अज्ञात फ़ंक्शन का संदर्भ जोड़ता है। यदि आप अज्ञात कार्यों से परिचित नहीं हैं यह ऐसा है:

pointer = function() {console.log(item + ' ' + list[i])};
result.push(pointer);

ध्यान दें कि जब आप उदाहरण चलाते हैं, तो "item2 undefined" तीन बार लॉग होता है! ऐसा इसलिए है क्योंकि पिछले उदाहरणों की तरह, buildList लिए स्थानीय चर के लिए केवल एक बंद है (जिसके result , i और item )। जब अज्ञात फ़ंक्शन लाइन fnlist[j]() पर कॉल किए जाते हैं; वे सभी एक ही बंद होने का उपयोग करते हैं, और वे उस बंद के भीतर i और item लिए वर्तमान मान का उपयोग करते हैं (जहां i पास 3 मान है क्योंकि लूप पूरा हो गया था, और item में 'item2' का मान है)। ध्यान दें कि हम 0 से अनुक्रमणित कर रहे हैं इसलिए item में item का मान है। और i ++ i मूल्य 3

यह देखने में मददगार हो सकता है कि क्या होता है जब भिन्न कीवर्ड के माध्यम से फ़ंक्शन-स्कोप्ड वेरिएबल घोषणा के बजाय वेरिएबल item की ब्लॉक-स्तरीय घोषणा का उपयोग किया जाता है ( let कीवर्ड के माध्यम से)। यदि वह परिवर्तन किया जाता है, तो सरणी result में प्रत्येक अज्ञात फ़ंक्शन का अपना बंद होना होता है; जब उदाहरण चलाया जाता है तो आउटपुट निम्नानुसार होता है:

item0 undefined
item1 undefined
item2 undefined

यदि वेरिएबल i को var बजाय let भी परिभाषित किया गया है, तो आउटपुट है:

item0 1
item1 2
item2 3

उदाहरण 7

इस अंतिम उदाहरण में, मुख्य समारोह में प्रत्येक कॉल एक अलग बंद बनाता है।

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

सारांश

अगर सब कुछ पूरी तरह से अस्पष्ट लगता है, तो उदाहरण के साथ खेलने के लिए सबसे अच्छी बात यह है कि। उदाहरणों को समझने से स्पष्टीकरण पढ़ना बहुत कठिन है। बंद करने और ढेर-फ्रेम, आदि की मेरी व्याख्या तकनीकी रूप से सही नहीं हैं - वे समझने में मदद करने के लिए सकल सरलीकरण हैं। एक बार मूल विचार grokked हो जाने के बाद, आप बाद में विवरण उठा सकते हैं।

अंतिम अंक:

  • जब भी आप किसी अन्य function अंदर function उपयोग function , तो बंद होने का उपयोग किया जाता है।
  • जब भी आप किसी फ़ंक्शन के अंदर eval() उपयोग करते हैं, तो एक बंद करने का उपयोग किया जाता है। आपके द्वारा eval पाठ फ़ंक्शन के स्थानीय चर का संदर्भ दे सकता है, और eval भीतर आप eval('var foo = …') का उपयोग करके नए स्थानीय चर भी बना सकते हैं।
  • जब आप new Function(…) अंदर new Function(…) ( फंक्शन कन्स्ट्रक्टर ) का उपयोग करते हैं, तो यह बंद नहीं होता है। (नया फ़ंक्शन बाहरी फ़ंक्शन के स्थानीय चर का संदर्भ नहीं दे सकता है।)
  • जावास्क्रिप्ट में एक बंद करना सभी स्थानीय चर की एक प्रति रखने की तरह है, जैसे कि जब कोई फ़ंक्शन निकलता था।
  • शायद यह सोचने के लिए सबसे अच्छा है कि एक बंद हमेशा एक समारोह में प्रवेश किया जाता है, और स्थानीय चर को उस बंद करने के लिए जोड़ा जाता है।
  • स्थानीय चर के एक नए सेट को हर बार एक बंद करने के साथ एक समारोह कहा जाता है (यह देखते हुए कि फ़ंक्शन में इसके अंदर एक फ़ंक्शन घोषणा है, और उस अंदर के फ़ंक्शन का संदर्भ या तो लौटाया गया है या किसी बाहरी तरीके से बाहरी संदर्भ रखा गया है )।
  • दो कार्य ऐसा लग सकते हैं कि उनके पास एक ही स्रोत टेक्स्ट है, लेकिन उनके 'छिपा' बंद होने के कारण पूरी तरह से अलग व्यवहार है। मुझे नहीं लगता कि जावास्क्रिप्ट कोड वास्तव में पता लगा सकता है कि फ़ंक्शन संदर्भ में बंद होना है या नहीं।
  • यदि आप कोई गतिशील स्रोत कोड संशोधन करने की कोशिश कर रहे हैं (उदाहरण के लिए: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola')); ), अगर myFunction एक बंद है तो यह काम नहीं करेगा ( बेशक, आप रनटाइम पर सोर्स कोड स्ट्रिंग प्रतिस्थापन करने के बारे में भी कभी नहीं सोचेंगे, लेकिन ...)।
  • कार्यों और mdash के भीतर फ़ंक्शन घोषणाओं के भीतर फ़ंक्शन घोषणाएं प्राप्त करना संभव है, और आप एक से अधिक स्तर पर बंद हो सकते हैं।
  • मुझे लगता है कि आम तौर पर बंद होने वाले चर के साथ दोनों कार्यों के लिए एक बंद शब्द होता है। ध्यान दें कि मैं इस आलेख में उस परिभाषा का उपयोग नहीं करता!
  • मुझे संदेह है कि जावास्क्रिप्ट में बंद होने वाले सामान्यतः कार्यात्मक भाषाओं में पाए जाते हैं।

लिंक

धन्यवाद

अगर आपने अभी बंद किया है (यहां या कहीं और!), तो मुझे आपके द्वारा सुझाए गए किसी भी बदलाव के बारे में किसी भी प्रतिक्रिया में दिलचस्पी है जो इस लेख को स्पष्ट कर सकता है। Morrisjohns.com (morris_closure @) को एक ईमेल भेजें। कृपया ध्यान दें कि मैं जावास्क्रिप्ट पर गुरु नहीं हूं - न ही बंद होने पर।

मॉरिस द्वारा मूल पोस्ट इंटरनेट आर्काइव में पाया जा सकता है।





javascript jquery ajax asynchronous upload