[javascript] 브라우저가 끌어서 놓기 파일을로드하지 못하도록 방지

내 페이지에 html5 드래그 앤 드롭 업 로더를 추가하고 있습니다.

파일을 업로드 영역에 놓으면 모든 것이 잘 작동합니다.

그러나 실수로 업로드 영역 외부에서 파일을 삭제하면 브라우저가 로컬 파일을 새 페이지 인 것처럼로드합니다.

이 동작을 어떻게 방지 할 수 있습니까?

감사!



답변

preventDefault()모든 드래그 앤 드롭 이벤트 를 호출하는 이벤트 리스너를 창에 추가 할 수 있습니다 .
예:

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


답변

많은 문제를 겪은 후 이것이 가장 안정적인 솔루션이라는 것을 알았습니다.

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를 허용하지 않습니다.


답변

jQuery의 경우 정답은 다음과 같습니다.

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

다음 return false과 같이 동작합니다 event.preventDefault()event.stopPropagation().


답변

일부 요소에서만 끌어서 놓기를 허용하려면 다음과 같이 할 수 있습니다.

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);


답변

이 시도:

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


답변

기본적으로 모든 끌어서 놓기 작업을 방지하는 것은 원하지 않을 수 있습니다. 적어도 일부 브라우저에서는 드래그 소스가 외부 파일인지 확인할 수 있습니다. 이 StackOverflow answer 에서 드래그 소스가 외부 파일인지 확인하는 기능을 포함 시켰습니다 .

Digital Plane의 답변을 수정하면 다음과 같이 할 수 있습니다.

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);


답변

참고 : OP는 Angular 솔루션을 요청하지 않았지만 여기를 찾아 왔습니다. 따라서 Angular를 사용하는 경우 가능한 해결책으로 찾은 것을 공유하는 것입니다.

내 경험상이 문제는 페이지에 파일 삭제 기능을 추가 할 때 처음 발생합니다. 따라서 내 의견으로는 이것을 추가하는 구성 요소가 드롭 영역 외부로 떨어지는 것을 방지해야 할 책임이 있다고 생각합니다.

내 솔루션에서 드롭 영역은 클래스가있는 입력이지만 모든 선택기가 작동합니다.

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';
    }
  }
}

리스너는 컴포넌트가 작성 / 파기 될 때 자동으로 추가 / 제거되며 동일한 페이지에서 동일한 전략을 사용하는 다른 컴포넌트는 stopPropagation ()으로 인해 서로 간섭하지 않습니다.