development

파일 또는 폴더를 놓기 전에 끌고 있는지 구별하는 방법은 무엇입니까?

big-blog 2020. 12. 12. 12:06
반응형

파일 또는 폴더를 놓기 전에 끌고 있는지 구별하는 방법은 무엇입니까?


폴더 나 파일이 dragover또는 dragenter이벤트 에서 드래그되었는지 감지하려고 합니다.

예를 들면 :

에서 ondrop이벤트라는 인수가 MouseEvent명명 된 필드가, dataTransfer파일을 나열, ( .files) 또는 항목 ( .items브라우저에 따라가), 나는 모두가 읽을 수 크롬파이어 폭스 . 그러나 dragoverdragenter이벤트의 경우 해당 필드 ( .files.items)가 비어 있습니다. 문제는 드래그하는 동안 해당 정보가 필요하다는 것 입니다.

참고 : 파일 및 폴더를 모두 들어가 event.dataTransfer.types[i] === "Files"있습니다 true.

배경 조사

내 질문에 부분적으로 적합한 다음 답변찾았 습니다 .

WebKit, 즉 Chrome은를 호출 할 수있는시기에 대해 매우 제한적입니다 getData. dragstart또는 내부에서 할 수 없습니다 dragover. 이것이 정식 버그라고 생각합니다.

그러나 그 대답은 2012 년부터이며 주제에 대한 실제 업데이트 된 정보를 찾을 수 없으므로 이에 대한 업데이트 된 정보를 찾고 있습니다.


TL; DR 당신은 할 수 없습니다 :(

이 질문에 여전히 허용 된 답변이없는 이유가 궁금하다면 OP에서 만든 이 메타 질문내 답변을 읽을 수 있습니다 .

파일 drag/ dropHTML5

이 주제에 대한 여러 문서를 조사하고 다양한 브라우저에서 직접 테스트 했으므로 여기에 파일 끌어서 놓기에 대해 알고있는 모든 내용을 요약하기로 결정했습니다.

질질 끄는

파일을 드래그 할 때 다음과 같은 일부 리스너를 사용할 수 있습니다.

  • dragenter
  • dragover
  • dragend
  • dragleave

이러한 것을 감안할 때 drag이벤트의 files의 속성 event.dataTransfer중 하나가됩니다 length == 0또는 비어를 ( null).

당신은 할 수없는 드래그 이벤트 파일의 내용을 읽고 당신이 할 수없는 그들이 폴더가 있는지 확인합니다. 이것은 버그가 아니라 보안 조치입니다.

드래그 이벤트에서 파일을 읽을 수 있다고 상상해보십시오. 사용자가 사이트에 파일을 업로드하고 싶지 않더라도 모든 것을 읽을 수 있습니다. 정말 말도 안 돼요. 데스크탑에서 다른 폴더로 파일을 드래그하고 실수로 웹 페이지를 통해 드래그한다고 상상해보십시오. 이제 웹 페이지가 파일을 읽고 서버에 개인 정보를 저장합니다 . 이는 엄청난 보안 결함이 될 것입니다.

그러나 사용자가 파일을 드래그하는지 (폴더가 파일이기 때문에 파일로도 폴더를 의미 함) 배열을 반복하여 드래그하는지 여부를 감지 할 수 있습니다 event.dataTransfer.types. 드래그 이벤트에 파일이 포함되어 있는지 확인하는 함수를 만든 다음 이벤트 핸들러에서 호출 할 수 있습니다.

예:

function containsFiles(event) {
    if (event.dataTransfer.types) {
        for (var i=0; i<event.dataTransfer.types.length; i++) {
            if (event.dataTransfer.types[i] == "Files") {
                return true;
            }
        }
    }

    return false;
}

function handleDragEnter(e) {
    e.preventDefault();
    if (containsFiles(e)) {
        // The drag event contains files
        // Do something
    } else {
        // The drag event doesn't contain files
        // Do something else
    }
}

적하

파일을 드롭 <div>(또는 드롭 존으로 사용중인 요소)에 드롭 하면 이벤트 drop대한 리스너를 사용하여 이름, 크기, 유형 및 마지막 수정 날짜와 같은 일부 파일 속성을 읽습니다.

파일이 폴더인지 감지하려면 다음을 수행하십시오.

  1. type == ""폴더에 유형이 없으므로 파일에이 있는지 확인하십시오 .
  2. size%4096 == 0폴더의 크기는 항상 4096 바이트 (4KiB)의 배수이므로 파일 크기가 4096 :의 배수인지 확인하십시오 .

예:

function handleDrop(e) {
    e.stopPropagation();
    e.preventDefault();

    var files = e.dataTransfer.files;

    for (var i = 0, f; f = files[i]; i++) { // iterate in the files dropped
        if (!f.type && f.size%4096 == 0) {
            // The file is a folder
            // Do something
        } else {
            // The file is not a folder
            // Do something else
        }
    }
}

알려진 문제 : 이 폴더는 실제로 파일이므로 다른 종류의 파일과 구별 할 수있는 유일한 방법입니다. 이 방법은 파일이 폴더라는 절대적인 확신을주지는 않지만 확장자가없고 크기가 0 또는 정확히 N x 4096B 인 파일 일 수 있습니다.


작업 예

Here are some working examples to see what I said above in action and test it by yourself. Before running them, make sure that your browser supports drag and drop features. Have fun:


This is work on Dropping -on drop event- (please note that this doesn't work on dragover event):

isDraggedItemIsFile = function(e) {
// handle FF
if (e.originalEvent.dataTransfer.files.length == 0) {
    return false;
}
// handle Chrome
if (e.originalEvent.dataTransfer.items) {
    if (typeof (e.originalEvent.dataTransfer.items[0].webkitGetAsEntry) == "function") {
        return e.originalEvent.dataTransfer.items[0].webkitGetAsEntry().isFile;
    } else if (typeof (e.originalEvent.dataTransfer.items[0].getAsEntry) == "function") {
        return e.originalEvent.dataTransfer.items[0].getAsEntry().isFile;
    }
}
return true;
};

$forms.on('drop', function(e) {
        if (isDraggedItemIsFile(e)) {
            // do something if file
        } else{
           // is directory
        }
    });

Tested on FF V49, Chrome V55, Edge V25


You can separate files from folders by using FileReader or with webkitGetAsEntry()

The webkitGetAsEntry() is not supported by ie11, so keep that in mind!

The code will look like:

 onDrop(event) {
    let files = event.dataTransfer ? event.dataTransfer.files : 'null';

    for(let i = 0, file; file = files[i]; i++) {
       var reader = new FileReader();

       reader.onload = function (e) {
           console.log('it is a file!');
       };
       reader.onerror = function (e) {
          console.log('it is a folder!');
       };

       reader.readAsText(file);
    }

}

I was able to get the entire Mimetype of the thing being dragged over my page. Mimetype appears to be blank for folders, so maybe you can distinguish it that way.

Partial code (extracted from React):

function handleDragOver(ev: DragEvent) {
    ev.preventDefault();
    ev.dataTransfer!.dropEffect = 'copy';
    console.log(Array.from(ev.dataTransfer.items).map(i => [i.kind,i.type].join('|')).join(', '));
}

document.addEventListener('dragover',handleDragOver);

Output looks like:

file|image/x-icon, file|image/jpeg, file|application/vnd.ms-excel

When I drag 3 files over my page.

Not sure if it only works on localhost, I haven't uploaded this anywhere yet, but it's totally working.

MDN docs on DataTransferItem

참고URL : https://stackoverflow.com/questions/25016442/how-to-distinguish-if-a-file-or-folder-is-being-dragged-prior-to-it-being-droppe

반응형