파일 또는 폴더를 놓기 전에 끌고 있는지 구별하는 방법은 무엇입니까?
폴더 나 파일이 dragover
또는 dragenter
이벤트 에서 드래그되었는지 감지하려고 합니다.
예를 들면 :
에서 ondrop
이벤트라는 인수가 MouseEvent
명명 된 필드가, dataTransfer
파일을 나열, ( .files
) 또는 항목 ( .items
브라우저에 따라가), 나는 모두가 읽을 수 크롬 과 파이어 폭스 . 그러나 dragover
및 dragenter
이벤트의 경우 해당 필드 ( .files
및 .items
)가 비어 있습니다. 문제는 드래그하는 동안 해당 정보가 필요하다는 것 입니다.
참고 : 파일 및 폴더를 모두 들어가 event.dataTransfer.types[i] === "Files"
있습니다 true
.
배경 조사
내 질문에 부분적으로 적합한 다음 답변 을 찾았 습니다 .
WebKit, 즉 Chrome은를 호출 할 수있는시기에 대해 매우 제한적입니다
getData
.dragstart
또는 내부에서 할 수 없습니다dragover
. 이것이 정식 버그라고 생각합니다.
그러나 그 대답은 2012 년부터이며 주제에 대한 실제 업데이트 된 정보를 찾을 수 없으므로 이에 대한 업데이트 된 정보를 찾고 있습니다.
TL; DR 당신은 할 수 없습니다 :(
이 질문에 여전히 허용 된 답변이없는 이유가 궁금하다면 OP에서 만든 이 메타 질문 과 내 답변을 읽을 수 있습니다 .
파일 drag
/ drop
HTML5
이 주제에 대한 여러 문서를 조사하고 다양한 브라우저에서 직접 테스트 했으므로 여기에 파일 끌어서 놓기에 대해 알고있는 모든 내용을 요약하기로 결정했습니다.
질질 끄는
파일을 드래그 할 때 다음과 같은 일부 리스너를 사용할 수 있습니다.
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
에 대한 리스너를 사용하여 이름, 크기, 유형 및 마지막 수정 날짜와 같은 일부 파일 속성을 읽습니다.
파일이 폴더인지 감지하려면 다음을 수행하십시오.
type == ""
폴더에 유형이 없으므로 파일에이 있는지 확인하십시오 .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:
- File drop display info (made by me)
- File/folder recognize (made by me)
- File drag detect (from css-tricks)
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.
'development' 카테고리의 다른 글
MySQL의 대소 문자 구분 데이터 정렬 (0) | 2020.12.12 |
---|---|
문자열 일치 후 단어를 가져 오는 정규식 (0) | 2020.12.12 |
urllib2.Request / urlopen으로 처리해야하는 오류 / 예외는 무엇입니까? (0) | 2020.12.12 |
여러 서버의 단일 SSL 인증서 (0) | 2020.12.12 |
Linux 패키지 저장소의 * -dev 패키지에는 실제로 무엇이 포함되어 있습니까? (0) | 2020.12.12 |