-
[JS] drag&drop 여러 디렉토리(폴더) 및 파일 업로드기능공부 2019. 5. 22. 14:43
js
FileSystem API
FileReader API
FileEntry API
nodejs
formidable
- 크롬에서 실습시 서버가 세팅되어있지 않은경우 참고
(설정 귀찮으면 다른브라우저 파이어폭스나 엣지 등을 사용)
서버가 없으면 브라우저에서 file:// 로 로컬파일에 접근하는건데
크롬의 경우 보안상 api를 이용해 file:// 로 접근하는걸 차단한다
크롬 옵션으로 해제
--allow-file-access-from-files
참고
https://developer.mozilla.org/en-US/docs/Web/API/FileError
For security reasons, browsers do not allow you to run your app from file://. In fact, many of the powerful storage APIs (such as File System, BlobBuilder, and FileReader) throw errors if you run the app locally from file://. When you're just testing your app, and you don't want to set up a web server, you can bypass the security restriction on Chrome. Just start Chrome with the --allow-file-access-from-files flag. Use the flag only for testing purposes.
크롬 --allow-file-access-from-files 옵션 설정하기
크롬창을 모두 종료한 뒤
chrome 설치위치로 가서 .\chrome.exe -allow-file-access-from-files 입력
C:\Program Files (x86)\Google\Chrome\Application>.\chrome.exe --allow-file-access-from-files또는 경로적고 바로적용
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files"크롬설치위치" --allow-file-access-from-files
입력시 새창이 뜬다
크롬창을 모두 닫은상태가 아니었다면 적용이 안된다 닫은후 다시해야함
설정은 크롬창을 모두 닫으면 초기화되어서 다음번에도 또 이렇게 열어야한다
html
<div class="container"> <div id="fileDropZone" >첨부파일을 이곳으로<br/>드래그하세요.</div> </div>css(적용안해도되지만 시각적으로)
.container{ display:flex; flex-direction: column; align-items : center; } #fileDropZone{ border : 2px gray dotted; padding : 50px; background-color : white; }
파일은 어떻게 읽나
드랍한 파일데이터를 어떻게 가져오나
디렉토리는 어떻게 읽나
알아볼 항목
File API
FileReader API
Blob 데이터
URL API
a태그의 download 속성
javascript
drag&drop 이벤트
dragover : 드래그객체가 해당영역 위에 올라와있을때
dragleave : 드래그객체가 해당영역에서 벗어남
drop : 영역에 drop
drag&drop 은 DataTransfer 객체 담는다.
drop이벤트 발생시 event객체에서 dataTransfer로 데이터 객체를 가져온다.
파일의 데이터자체를 읽으려면
파일을 File 객체로 가져와야한다.이 File 객체를 FileReader 객체의 api들로 읽는다.
-
FileReader API
readAsText(file) : 텍스트로 읽는다
readAsDataURL(file) : blob형식이 URL로 인코딩하여 읽는다. (값을 src속성에 활용할 수도 있다.)
주소창에 이 값을 입력하면 브라우저가 알아서해석해서 원래대로 표현한다.
readAsArrayBuffer(file) : blog형식의 바이너리가 ArrayBuffer 객체로 반환됨
readAsBinaryString(file) : blob 형식의 바이너리문자열로 반환
발생이벤트에 함수를 붙여 핸들러처리
onloadstart
onload : 로드완료
onloadend
onprogress : 진행되는중 (진행률 표시하고싶을때 사용가능)
onabort
onerror : 에러
*파일을 chunk로 다루려면 FILE 객체의 slice 메소드 사용
주요 함수와 반환값들
- event.dataTransfer
>DataTransfer 객체 반환
- dataTransfer.files
>FileList 객체를 반환
FileList는 File객체를 갖고있다.
이 File은 FileReader 객체의 api로 읽으면 파일자체의 데이터를 얻을 수 있다.
파일만 드랍된 경우 이 객체에서 데이터를 가져오면 된다.
- dataTransfer.items
>DataTransferItemList 객체 반환
dataTransferItemList은 dataTransferItem을 가진 유사배열(인덱스가 키인 객체)임
dataTransferItem은 문자열일 수도 파일/디렉토리 일수도있다.
dataTransferItem.kind 속성은 string이나 file값을 반환한다.
dataTransferItem.type 속성은 데이터의 type/format 값을 반환한다.
*파일인경우 dataTransferItem은 dataTransferItem.getAsFile() 메소드로 File객체로 변환가능
드랍한것이 디렉터리일경우 디렉터리탐색을 위해선 Entry 객체로 변환해야함
파일/디렉토리 구분은 다음 속성을 이용해 판별
dataTransferItem.isFile => true/false
dataTransferItem.isDirectory => true/false
- dataTransferItem.webkitGetAsEntry()
디렉토리면 > FileSystemDirectoryEntry 객체 반환
파일이면 > FileSystemFileEntry 객체 반환
*fileSystemFileEntry.file(successcallback, [errorcallback]) 메소드로 File 객체를 얻을 수 있다.
엣지는 Webkit기반이 아니기라 객체가 다르다. WebKitFileEntry와 WebKitDirectoryEntry로 반환
FileSystemEntry의 속성
filesystem
name : 이름
isFile : 파일인지 true/false
isDirectory :디렉토리인지
fullPath : 드랍된 객체를 기준으로한 경로
FileSystemEntry 의 속성은 모두 ReadOnly이다. 변경할 수 없다.
https://developer.mozilla.org/en-US/docs/Web/API/FileSystemEntry
- fileSystemDirectoryEntry.createReader()
>FileSystemDirectoryReader 객체 반환
엣지는 WebKitDirectoryReader
- fileSystemDirectoryReader.readEntries(successcallback, [errorcallback])
callback함수는 entries를 인자로 갖고 entries에 디렉토리 내용물(파일/디렉토리)들이 담긴다.
디렉토리면 > FileSystemDirectoryEntry 객체
파일이면 > FileSystemFileEntry 객체
readEntries메소드는 비동기로 처리되기 때문에
디렉토리에 하위 디렉토리가 있는경우 promise나 async/await 문법으로 순서를 맞춰주는 것이 좋다.
파일을 다운로드할때 ajax작성해서 서버에 비동기요청을
보내고 응답을 받고 하는 과정이 번거로우면
a태그의 download 속성 이용
<a download="파일이름">클릭해서 다운로드</a>
let blog = new Blob(데이터,{type: 'type/format'})
let url = URL.createObject(blob) //이진데이터를 url형태로 인코딩
a.href = url
지정시 해당 파일이름으로 url요청=>이진데이터 다운로드
Blob(array, options)
array는 ArrayBuffer, ArrayBufferView, Blob, DOMString 객체가 온다
options는 객체 {key : value} 형태로 전달한다.
URL(blob)
blob는 Blob, File 객체가 온다.
필요한모듈과 용도
formidable : FormData 파싱
fs : 파일시스템 제어
path : 디렉토리 생성시 경로설정 편하게
const form = formidable.IncomingForm(); form.parse(req, (err, fields, files)=>{ // Ojbect.keys(files)로 키배열 얻고 배열함수로 순환하며 객체를 차례대로 접근해 처리 });한글있는 파일이 안깨지려면 html파일 <head>에 <meta charset="utf-8" /> 넣어야한다.
form.encoding = "utf-8"; //저장시 인코딩깨진다면 설정변경
form.keepExtensions = true; //uploadDir 경로에 파일쓸 때 원래 확장자로 사용하려면
경로변경
fs.renameSync(oldpath, newpath)임시저장소에서 쉽게 원하는 경로로 변경가능하다.
※디스크 파티션이 다른경우 에러※
Error: EXDEV, cross-device link not permitted
임시저장디렉토리와 지정한 디렉토리의 디스크 파티션이 다른경우처리하기전 uploadDir 를 설정해 같은 파티션내로 변경
const form = formidable.IncomingForm(); form.uploadDir = __dirname + "/tmp"form.on(event, callback) : 이벤트처리
form.parse()로 파싱하면서 발생하는 이벤트처리
form.on("progress", callback(byteReceived, byteExpected){ }) //중간처리과정알림. progress bar 만들때 보통 사용
form.on("error", callback(err){ }) //에러발생시
form.on("end", callback( ){ }) //파일처리가 모두 끝난 뒤 발생
Formidable의 File 객체
file.size
file.path
file.name
file.type
'공부' 카테고리의 다른 글
[Web] 안전한 웹사이트는 어떻게 만들까 (0) 2019.05.02 [JS/CSS] Carousel (Slider)은 어떻게 만들까 (0) 2019.05.01