File APIs 를 이용하여 자바스크립트로 파일들을 읽어보기
HTML5는 마침내 File API 사양을 통해 로컬 파일과 상호 작용하는 표준 방법을 제공합니다 . 기능의 예로 File API를 사용하여 이미지가 서버로 전송되는 동안 미리보기 이미지 미리보기를 만들거나 사용자가 오프라인 상태 일 때 앱이 파일 참조를 저장할 수 있습니다. 또한 클라이언트 측 로직을 사용하여 업로드의 MIME 유형이 파일 확장자와 일치하는지 확인하거나 업로드 크기를 제한 할 수 있습니다.
이 스펙은 '로컬'파일 시스템에서 파일에 액세스하기위한 몇 가지 인터페이스를 제공합니다.
File
- 개별 파일; 이름, 파일 크기, MIME 형식 및 파일 핸들에 대한 참조와 같은 읽기 전용 정보를 제공합니다.FileList
- 배열과 같은 일련의 File
객체. ( <input type="file" multiple>
데스크탑에서 파일 디렉토리를 생각 하거나 드래그).Blob
- 파일을 바이트 범위로 분할 할 수 있습니다.위의 데이터 구조와 함께 FileReader
사용하면 익숙한 JavaScript 이벤트 처리를 통해 비동기 적으로 파일을 읽을 수 있습니다. 따라서 읽기 진행률을 모니터링하고 오류를 catch하고로드가 완료된시기를 판별하는 것이 가능합니다. 여러면에서 API는 XMLHttpRequest
이벤트 모델 과 유사 합니다.
가장 먼저 할 일은 브라우저가 File API를 완벽하게 지원하는지 확인하는 것입니다.
// Check for the various File API support. if (window.File && window.FileReader && window.FileList && window.Blob) { // Great success! All the File APIs are supported. } else { alert('The File APIs are not fully supported in this browser.'); }
물론 앱에서 이러한 API 중 일부만 사용하는 경우 snippet 을 수정하세요.
파일을로드하는 가장 간단한 방법은 표준 <input type="file">
요소 를 사용하는 것 입니다. JavaScript는 선택한 File
객체 의 목록을 FileList 로 반환합니다. 한 번에 여러 파일을 선택할 수 있도록 'multiple'속성을 사용하는 예는 다음과 같습니다.
<input type="file" id="files" name="files[]" multiple /> <output id="list"></output> <script> function handleFileSelect(evt) { var files = evt.target.files; // FileList object // files is a FileList of File objects. List some properties. var output = []; for (var i = 0, f; f = files[i]; i++) { output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>'); } document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>'; } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script>
파일을 로드 하는 또 다른 기술은 데스크탑에서 브라우저로 기본 드래그 앤 드롭입니다. 드래그 앤 드롭 지원을 포함하도록 앞의 예제를 약간 수정할 수 있습니다.
<div id="drop_zone">Drop files here</div> <output id="list"></output> <script> function handleFileSelect(evt) { evt.stopPropagation(); evt.preventDefault(); var files = evt.dataTransfer.files; // FileList object. // files is a FileList of File objects. List some properties. var output = []; for (var i = 0, f; f = files[i]; i++) { output.push('<li><strong>', escape(f.name), '</strong> (', f.type || 'n/a', ') - ', f.size, ' bytes, last modified: ', f.lastModifiedDate ? f.lastModifiedDate.toLocaleDateString() : 'n/a', '</li>'); } document.getElementById('list').innerHTML = '<ul>' + output.join('') + '</ul>'; } function handleDragOver(evt) { evt.stopPropagation(); evt.preventDefault(); evt.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. } // Setup the dnd listeners. var dropZone = document.getElementById('drop_zone'); dropZone.addEventListener('dragover', handleDragOver, false); dropZone.addEventListener('drop', handleFileSelect, false); </script>
참고 : 일부 브라우저는 <input type="file">
요소를 기본 드롭 대상으로 처리 합니다. 앞의 예제에서 파일을 입력 필드로 드래그 해 보십시오.
이제 재미있는 부분이 있습니다!
File
레퍼런스를 얻은 후에 FileReader
객체를 인스턴스화하여 내용을 메모리로 읽어들입니다. 로드가 끝나면 reader 의 onload
이벤트가 시작되고 해당 result
속성을 사용하여 파일 데이터에 액세스 할 수 있습니다.
FileReader
비동기 적으로 파일을 읽는 네 가지 옵션이 있습니다.
FileReader.readAsBinaryString(Blob|File)
- result
속성에는 파일 / blob의 데이터가 바이너리 문자열로 포함됩니다. 모든 바이트는 [0..255] 범위의 정수로 표시됩니다.FileReader.readAsText(Blob|File, opt_encoding)
- result
속성은 파일 / blob의 데이터를 텍스트 문자열로 포함합니다. 기본적으로 문자열은 'UTF-8'로 디코딩됩니다. 선택적 인코딩 매개 변수를 사용하여 다른 형식을 지정할 수 있습니다.FileReader.readAsDataURL(Blob|File)
- result
속성에는 데이터 URL로 인코딩 된 파일 / blob의 데이터가 포함됩니다 .FileReader.readAsArrayBuffer(Blob|File)
- result
속성에는 파일 / blob의 데이터가 ArrayBuffer 객체로 포함됩니다.이러한 읽기 방법 중 하나를 한 번에 호출 FileReader
객체는 onloadstart
, onprogress
, onload
, onabort
, onerror
, 및 onloadend
진행 상황을 추적 할 수 있습니다.
아래의 예는, 사용자의 선택의 이미지를 필터링 호출 reader.readAsDataURL()
파일에, 데이터 URL에 'SRC'속성을 설정하여 미리보기를 렌더링합니다.
<style> .thumb { height: 75px; border: 1px solid #000; margin: 10px 5px 0 0; } </style> <input type="file" id="files" name="files[]" multiple /> <output id="list"></output> <script> function handleFileSelect(evt) { var files = evt.target.files; // FileList object // Loop through the FileList and render image files as thumbnails. for (var i = 0, f; f = files[i]; i++) { // Only process image files. if (!f.type.match('image.*')) { continue; } var reader = new FileReader(); // Closure to capture the file information. reader.onload = (function(theFile) { return function(e) { // Render thumbnail. var span = document.createElement('span'); span.innerHTML = ['<img class="thumb" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join(''); document.getElementById('list').insertBefore(span, null); }; })(f); // Read in the image file as a data URL. reader.readAsDataURL(f); } } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script>
어떤 경우에는 전체 파일을 메모리로 읽어들이는 것이 최선의 방법은 아닙니다. 예를 들어 비동기 파일 업 로더를 작성하려고한다고 가정 해보십시오. 업로드 속도를 높이는 한 가지 방법은 별도의 바이트 범위 chunk 로 파일을 읽고 보내는 것입니다. 그런 다음 서버 구성 요소는 올바른 순서로 파일 내용을 재구성해야합니다.
운 좋게도 이 File
인터페이스는 이 사용 사례를 지원하는 슬라이스 메서드를 지원합니다. 이 메서드는 시작 바이트를 첫 번째 인수로 사용하고 바이트를 두 번째로 끝내고 옵션 콘텐츠 형식 문자열을 세 번째 인수로 사용합니다.
var blob = file.slice(startingByte, endindByte); reader.readAsBinaryString(blob);
다음 예제에서는 하나의 파일의 chunk 읽기를 보여줍니다. 주목할 부분은 onloadend
사용하는 것과, onload 이벤트를 사용하지 않고 evt.target.readyState 를 체크 한다는 것입니다.
<style> #byte_content { margin: 5px 0; max-height: 100px; overflow-y: auto; overflow-x: hidden; } #byte_range { margin-top: 5px; } </style> <input type="file" id="files" name="file" /> Read bytes: <span class="readBytesButtons"> <button data-startbyte="0" data-endbyte="4">1-5</button> <button data-startbyte="5" data-endbyte="14">6-15</button> <button data-startbyte="6" data-endbyte="7">7-8</button> <button>entire file</button> </span> <div id="byte_range"></div> <div id="byte_content"></div> <script> function readBlob(opt_startByte, opt_stopByte) { var files = document.getElementById('files').files; if (!files.length) { alert('Please select a file!'); return; } var file = files[0]; var start = parseInt(opt_startByte) || 0; var stop = parseInt(opt_stopByte) || file.size - 1; var reader = new FileReader(); // If we use onloadend, we need to check the readyState. reader.onloadend = function(evt) { if (evt.target.readyState == FileReader.DONE) { // DONE == 2 document.getElementById('byte_content').textContent = evt.target.result; document.getElementById('byte_range').textContent = ['Read bytes: ', start + 1, ' - ', stop + 1, ' of ', file.size, ' byte file'].join(''); } }; var blob = file.slice(start, stop + 1); reader.readAsBinaryString(blob); } document.querySelector('.readBytesButtons').addEventListener('click', function(evt) { if (evt.target.tagName.toLowerCase() == 'button') { var startByte = evt.target.getAttribute('data-startbyte'); var endByte = evt.target.getAttribute('data-endbyte'); readBlob(startByte, endByte); } }, false); </script>
비동기 이벤트 처리를 사용할 때 우리가 무료로 얻을 수있는 좋은 점 중 하나는 파일 읽기의 진행 상황을 모니터하는 기능입니다. 대용량 파일에 유용하고, 오류를 포착하고, 읽기가 완료된시기를 파악할 수 있습니다.
the onloadstart
및 onprogress
events는 읽기 진행을 모니터하는 데 사용할 수 있습니다.
아래 예제는 진행 상태 막대를 표시하여 읽기 상태를 모니터링하는 방법을 보여줍니다. 작동중인 진행률 표시기를 보려면 큰 파일이나 원격 드라이브에서 파일을 시도하십시오.
<style> #progress_bar { margin: 10px 0; padding: 3px; border: 1px solid #000; font-size: 14px; clear: both; opacity: 0; -moz-transition: opacity 1s linear; -o-transition: opacity 1s linear; -webkit-transition: opacity 1s linear; } #progress_bar.loading { opacity: 1.0; } #progress_bar .percent { background-color: #99ccff; height: auto; width: 0; } </style> <input type="file" id="files" name="file" /> <button onclick="abortRead();">Cancel read</button> <div id="progress_bar"><div class="percent">0%</div></div> <script> var reader; var progress = document.querySelector('.percent'); function abortRead() { reader.abort(); } function errorHandler(evt) { switch(evt.target.error.code) { case evt.target.error.NOT_FOUND_ERR: alert('File Not Found!'); break; case evt.target.error.NOT_READABLE_ERR: alert('File is not readable'); break; case evt.target.error.ABORT_ERR: break; // noop default: alert('An error occurred reading this file.'); }; } function updateProgress(evt) { // evt is an ProgressEvent. if (evt.lengthComputable) { var percentLoaded = Math.round((evt.loaded / evt.total) * 100); // Increase the progress bar length. if (percentLoaded < 100) { progress.style.width = percentLoaded + '%'; progress.textContent = percentLoaded + '%'; } } } function handleFileSelect(evt) { // Reset progress indicator on new file selection. progress.style.width = '0%'; progress.textContent = '0%'; reader = new FileReader(); reader.onerror = errorHandler; reader.onprogress = updateProgress; reader.onabort = function(e) { alert('File read cancelled'); }; reader.onloadstart = function(e) { document.getElementById('progress_bar').className = 'loading'; }; reader.onload = function(e) { // Ensure that the progress bar displays 100% at the end. progress.style.width = '100%'; progress.textContent = '100%'; setTimeout("document.getElementById('progress_bar').className='';", 2000); } // Read in the image file as a binary string. reader.readAsBinaryString(evt.target.files[0]); } document.getElementById('files').addEventListener('change', handleFileSelect, false); </script>
facebook login, Graph API, Sharing 알아보기 (www.fbrell.com) (0) | 2017.10.13 |
---|---|
javascript 로 파일 다운로드 처리하기 (javascript file download) ✔ (2) | 2017.09.21 |
아이프레임 iframe 리사이즈 resize 조절 하는 방법 (0) | 2017.08.09 |
Javascript key code 자바스크립트 키코드 알아보기 (0) | 2017.05.31 |
javascript email check 이메일 체크 (0) | 2017.02.20 |