किसी ड्रैग-एंड-ड्रॉप फ़ाइल को लोड करने से ब्राउज़र को रोकें


194

मैं अपने पृष्ठ पर एक html5 ड्रैग और ड्रॉप अपलोडर जोड़ रहा हूँ।

जब एक फ़ाइल अपलोड क्षेत्र में गिरा दी जाती है, तो सब कुछ बहुत अच्छा काम करता है।

हालाँकि, यदि मैं गलती से फ़ाइल को अपलोड क्षेत्र के बाहर छोड़ देता हूं, तो ब्राउज़र स्थानीय फ़ाइल को ऐसे लोड करता है मानो वह कोई नया पृष्ठ हो।

मैं इस व्यवहार को कैसे रोक सकता हूं?

धन्यवाद!


2
HTML5 ड्रैग / ड्रॉप अपलोडिंग को संभालने के लिए आप किस कोड का उपयोग कर रहे हैं, इसके लिए उत्सुक हैं। धन्यवाद।
रोबर्टब्रेडफोर्ड

आपके द्वारा की गई समस्या या तो e.dataTransfer () या अनुपलब्धDefault () ड्रॉप / ड्रैगेंटर / आदि के गुम होने के कारण है। आयोजन। लेकिन मैं एक कोड नमूने के बिना नहीं बता सकता।
होल्डऑफहिंगर

जवाबों:


313

आप विंडो में एक ईवेंट श्रोता को जोड़ सकते हैं जो preventDefault()सभी ड्रैगओवर और ड्रॉप ईवेंट पर कॉल करता है।
उदाहरण:

window.addEventListener("dragover",function(e){
  e = e || event;
  e.preventDefault();
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
},false);

45
ड्रैगओवर वह टुकड़ा है जिसे मैं याद कर रहा था।
19

11
मैं पुष्टि करता हूं कि ब्राउज़र dragoverऔर dropहैंडलर दोनों को गिराए गए फ़ाइल को लोड करने से रोकने के लिए आवश्यक है। (क्रोम नवीनतम 2015/08/03)। समाधान एफएफ नवीनतम पर भी काम करता है।
ऑफिशो

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

15
नोट: यह भी एक पर फ़ाइलों को खींचने को अक्षम करता है <input type="file" />। यह जांचना आवश्यक है कि क्या e.targetफ़ाइल इनपुट है और इस तरह की घटनाओं के माध्यम से जाने दें।
सेबेस्टियन नोवाक

6
क्या ? विंडो ड्रैगओवर फ़ाइल को लोड क्यों करना चाहिए? इसका कोई मतलब नहीं है ...
L.Trabacchin

38

चारों ओर बहुत सी हलचल के बाद, मैंने इसे स्टैब्लेस्टर समाधान पाया:

var dropzoneId = "dropzone";

window.addEventListener("dragenter", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
}, false);

window.addEventListener("dragover", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});

window.addEventListener("drop", function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.effectAllowed = "none";
    e.dataTransfer.dropEffect = "none";
  }
});
<div id="dropzone">...</div>

दोनों effectAllowऔर dropEffectबिना शर्त खिड़की पर सेट करने से मेरे ड्रॉप ज़ोन को किसी भी dnd को स्वीकार नहीं करने का कारण बनता है, भले ही गुण नए सेट हों या नहीं।


e.dataTransfer () यहाँ महत्वपूर्ण कृति है जो इस कार्य को करती है, जिसका "स्वीकृत उत्तर" उल्लेख करने में विफल रहा।
होल्डऑफहिंगर

9

JQuery के लिए सही उत्तर होगा:

$(document).on({
    dragover: function() {
        return false;
    },
    drop: function() {
        return false;
    }
});

यहाँ return falseके रूप में व्यवहार करेंगे event.preventDefault()और event.stopPropagation()


9

केवल कुछ तत्वों पर ड्रैग-एंड-ड्रॉप की अनुमति देने के लिए, आप कुछ ऐसा कर सकते हैं:

window.addEventListener("dragover",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") { // check which element is our target
    e.preventDefault();
  }
},false);
window.addEventListener("drop",function(e){
  e = e || event;
  console.log(e);
  if (e.target.tagName != "INPUT") {  // check which element is our target
    e.preventDefault();
  }  
},false);

मेरे लिए बिल्कुल सही काम करता है, लेकिन मैं टाइप = फ़ाइल के लिए चेक भी
जोड़ूंगा

2

इसे इस्तेमाल करे:

document.body.addEventListener('drop', function(e) {
    e.preventDefault();
}, false);

2

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

डिजिटल प्लेन के उत्तर को संशोधित करते हुए, आप कुछ इस तरह कर सकते हैं:

function isDragSourceExternalFile() {
     // Defined here: 
     // https://stackoverflow.com/a/32044172/395461
}

window.addEventListener("dragover",function(e){
    e = e || event;
    var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
    if (IsFile) e.preventDefault();
},false);
window.addEventListener("drop",function(e){
    e = e || event;
    var IsFile = isDragSourceExternalFile(e.originalEvent.dataTransfer);
    if (IsFile) e.preventDefault();
},false);

1
किस बात का e || event;? कहाँ eventपरिभाषित किया गया है? कोई बात नहीं। ऐसा लगता है कि यह IE में एक वैश्विक वस्तु है? मुझे यह उद्धरण मिला, "In Microsoft Visual Basic Scripting Edition (VBScript), you must access the event object through the window object." यहां
1.21 गीगावाट

2

नोट: यद्यपि ओपी ने एक कोणीय समाधान के लिए नहीं कहा था, मैं यहाँ उस की तलाश में आया था। तो यह साझा करने के लिए है कि मुझे क्या व्यवहार्य समाधान मिला, अगर आप कोणीय का उपयोग करते हैं।

मेरे अनुभव में यह समस्या तब उत्पन्न होती है जब आप किसी पृष्ठ पर फ़ाइल ड्रॉप कार्यक्षमता जोड़ते हैं। इसलिए मेरी राय है कि जो घटक इसे जोड़ता है, उसे ड्रॉप ज़ोन के बाहर ड्रॉप को रोकने के लिए भी जिम्मेदार होना चाहिए।

मेरे समाधान में ड्रॉप ज़ोन एक वर्ग के साथ एक इनपुट है, लेकिन कोई भी अस्पष्ट चयनकर्ता काम करता है।

import { Component, HostListener } from '@angular/core';
//...

@Component({
  template: `
    <form>
      <!-- ... -->
      <input type="file" class="dropzone" />
    </form>
  `
})
export class MyComponentWithDropTarget {

  //...

  @HostListener('document:dragover', ['$event'])
  @HostListener('drop', ['$event'])
  onDragDropFileVerifyZone(event) {
    if (event.target.matches('input.dropzone')) {
      // In drop zone. I don't want listeners later in event-chain to meddle in here
      event.stopPropagation();
    } else {
      // Outside of drop zone! Prevent default action, and do not show copy/move icon
      event.preventDefault();
      event.dataTransfer.effectAllowed = 'none';
      event.dataTransfer.dropEffect = 'none';
    }
  }
}

जब घटक बनाए / नष्ट किए जाते हैं, तो श्रोता अपने आप जुड़ जाते हैं / हटा दिए जाते हैं, और एक ही पृष्ठ पर एक ही रणनीति का उपयोग करने वाले अन्य घटक स्टॉपप्रोपैजेशन () के कारण एक-दूसरे के साथ हस्तक्षेप नहीं करते हैं।


यह एक आकर्षण की तरह काम करता है !! ब्राउज़र भी माउस कर्सर को एक प्रतिबंध आइकन जोड़कर बदल देता है जो इतना महान है !!
pti_jul

1

कुछ अन्य उत्तरों में उल्लिखित "लक्ष्य की जाँच करें" विधि के निर्माण के लिए, यहाँ एक अधिक सामान्य / कार्यात्मक तरीका है:

function preventDefaultExcept(predicates) {
  return function (e) {
    var passEvery = predicates.every(function (predicate) { return predicate(e); })
    if (!passEvery) {
      e.preventDefault();
    }
  };
}

जैसे कहा जाता है:

function isDropzone(e) { return e.target.id === 'dropzone'; }
function isntParagraph(e) { return e.target.tagName !== 'p'; }

window.addEventListener(
  'dragover',
  preventDefaultExcept([isDropzone, isntParagraph])
);
window.addEventListener(
  'drop',
  preventDefaultExcept([isDropzone])
);

इसके अलावा, यहाँ कुछ ES6 जोड़ सकते हैं function preventDefaultExcept(...predicates){}:। और फिर इसे इस्तेमाल करेंpreventDefaultExcept(isDropzone, isntParagraph)
hlfrmn

0

मेरे पास एक HTML object( embed) है जो पृष्ठ की चौड़ाई और ऊंचाई को भरता है। @ डिजिटल-प्लेन द्वारा दिया गया उत्तर सामान्य वेब पेजों पर काम करता है, लेकिन यदि उपयोगकर्ता किसी एम्बेडेड ऑब्जेक्ट पर ड्रॉप नहीं करता है। इसलिए मुझे एक अलग समाधान की आवश्यकता थी।

यदि हम ईवेंट कैप्चर चरण का उपयोग करने के लिए स्विच करते हैं, तो हम इवेंट प्राप्त कर सकते हैं इससे पहले कि एम्बेडेड ऑब्जेक्ट उन्हें प्राप्त हो (नोटिस trueश्रोता कॉल के अंत में मूल्य देखें):

// document.body or window
document.body.addEventListener("dragover", function(e){
  e = e || event;
  e.preventDefault();
  console.log("over true");
}, true);

document.body.addEventListener("drop", function(e){
  e = e || event;
  e.preventDefault();
  console.log("drop true");
}, true);

निम्न कोड (@ डिजिटल-प्लेन के उत्तर के आधार पर) का उपयोग करने से पृष्ठ एक ड्रैग टारगेट बन जाता है, यह ऑब्जेक्ट को घटनाओं को कैप्चर करने से रोकता है और फिर हमारी छवियों को लोड करता है:

document.body.addEventListener("dragover", function(e){
  e = e || event;
  e.preventDefault();
  console.log("over true");
}, true);

document.body.addEventListener("drop",function(e){
  e = e || event;
  e.preventDefault();
  console.log("Drop true");

  // begin loading image data to pass to our embed
  var droppedFiles = e.dataTransfer.files;
  var fileReaders = {};
  var files = {};
  var reader;

  for (var i = 0; i < droppedFiles.length; i++) {
    files[i] = droppedFiles[i]; // bc file is ref is overwritten
    console.log("File: " + files[i].name + " " + files[i].size);
    reader = new FileReader();
    reader.file = files[i]; // bc loadend event has no file ref

    reader.addEventListener("loadend", function (ev, loadedFile) {
      var fileObject = {};
      var currentReader = ev.target;

      loadedFile = currentReader.file;
      console.log("File loaded:" + loadedFile.name);
      fileObject.dataURI = currentReader.result;
      fileObject.name = loadedFile.name;
      fileObject.type = loadedFile.type;
      // call function on embed and pass file object
    });

    reader.readAsDataURL(files[i]);
  }

}, true);

मैक पर फ़ायरफ़ॉक्स पर परीक्षण किया गया।


0

मैं कई अपलोड क्षेत्रों के लिए एक वर्ग चयनकर्ता का उपयोग कर रहा हूं इसलिए मेरे समाधान ने इसे कम शुद्ध रूप में लिया

JQuery पर निर्भरता के साथ एक्सल अमथोर के जवाब के आधार पर ($ के लिए उपनाम)

_stopBrowserFromOpeningDragAndDropPDFFiles = function () {

        _preventDND = function(e) {
            if (!$(e.target).is($(_uploadBoxSelector))) {
                e.preventDefault();
                e.dataTransfer.effectAllowed = 'none';
                e.dataTransfer.dropEffect = 'none';
            }
        };

        window.addEventListener('dragenter', function (e) {
            _preventDND(e);
        }, false);

        window.addEventListener('dragover', function (e) {
            _preventDND(e);
        });

        window.addEventListener('drop', function (e) {
            _preventDND(e);
        });
    },
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.