[WebDevCurriculum] file load/save as

1. file load(by vanillaJS)

file을 read하는 별도의 class와 method 등을 활용한다.

  • file loader와 Image를 확인할 수 있는 공간(Thumbnail)을 구성한다.
<input class="loader" type="file" accept="*" />
		<div class="divisionpreviewImage">
			<img src="" class="previewImage" alt="Check Image here">
		</div>
  • 활용해야 할 변수를 선언한다.
    → FileReader(VanillaJS에 내장되어있는 class, file load 후 url 정보를 읽음)
    → preview(upload한 image가 저장되는 공간)
    → fileInput(file을 upload하는 특수 tag(인터페이스 상 버튼))
// file read(upload) logic
	let reader = new FileReader();
	let preview = document.querySelector('img.previewImage');
	let fileInput = document.querySelector('input[type="file"]');
  • file upload logic을 구성한다.
    → selectedFile(upload event가 발생한다면 최종적으로 이미지정보가 담기는 장소)
    → upload를 하려고 하는 시점에서 change Event감지, if(selectedFile) 분기문 실행
    → 최종적으로 load가 되는 시점에서 저장되어있는 readAsDataURL(=reader.result), Event 실행에 따라 preview.src(이미지 저장 장소)에 해당 정보가 담긴다.
fileInput.addEventListener('change', whenfileReaderSelected);

		function handleEvent(e){
			console.log('img.src');
			preview.src = reader.result;
		};
		

		function whenfileReaderSelected(e){
			let selectedFile = fileInput.files[0];

			if(selectedFile){
				console.log(fileInput.files)
				reader.addEventListener('load', handleEvent);
			}	
				
			console.log('image.src is ', preview.src);
			console.log('fileInput.files[0] is ', selectedFile);
				
			reader.readAsDataURL(selectedFile);
			console.log('readAsDataURL');
			};
	}
  • ※ 최종적으로 진행하는 logic 순서
    1) 업로드 버튼 클릭으로 selectedFile에 정보담김, 분기실행
    2) reader가 file upload / read event를 listen
    3) reader는 readAsDataURL로 url 정보를 이미 저장하고 있으며, 최종적으로 load를 하면서 preview.src에 해당 정보가 저장되어 출력된다.

2. 간단한 문자열의 local storage 저장

local storage를 활용하여 간단한 문자열을 저장할 수 있다.

  • reader.readAsDataURL이나 reader.result 등 file 정보가 담겨져 있는 변수를 server, local storage 등 원하는 장소에 저장할 수 있다.
  • 위의 file load를 통해 확보한 URL을 local storage에 저장하는 간단한 예시이다.

localStorage.setItem('0', preview.src)

3. file 생성하고 다운로드 및 저장하기

text editor에 담겨진 내용을 file로 만들어 PC에 저장하는 logic을 구성한다.

3-1. file create(save as)

text editor에 작성한 내용을 PC에 file로 생성하여 저장한다.

  • textArea(글자를 작성하는 영역), button(저장하는 버튼)에 대한 element를 생성한다.
let saveButton = document.querySelector('.saveButton');
let textArea = document.querySelector('.textArea');
  • Button요소에 click event를 추가한 후, 저장하는 logic을 구성한다.
  • 저장하는 logic은 Blob , anchor element를 통한 download logic을 활용한다.
saveButton.addEventListener('click', ()=>{
			downloadFunction(textArea.value, 'file.txt', 'text/plain');
		})

		function downloadFunction(content, fileName, fileType){
			const a = document.createElement('a');
			const textFile = new Blob([content], {type: fileType});
		
			a.href = URL.createObjectURL(textFile);
			a.download = fileName;
			a.click();

			URL.revokeObjectURL(a.href);
		}
  • 브라우저에서 버튼을 눌렀을때 text file을 저장하는 logic 흐름은 아래와 같다.
    → Blob을 통해 textfile을 생성할 객체가 생성되었다.
    → anchor 객체를 통해 textfile에 대한 정보를 href에 저장하여 담는다.
    → 해당 객체는 최종적으로 URL string(URL.createObjectURL)이 담겨있으며, download / click() method를 통해 브라우저에서 파일이 다운로드 및 저장된다.

3-2. **file save

file create/save as가 아닌 임시저장(editor save)은 어떻게 구현할 수 있을지 고민해본다.

4. unsaved indicator(문구 나타내기)

text editor의 내용변화을 감지하고 unsaved 문구를 표시한다.

  • 우선 unsaved 문구를 표시하기 위한 구획을 따로 설정해주었다.

element declation

  • element 정의 및 createTextNode를 통해 문구 element까지 생성
    → messageBox를 나타낼 구획과, 해당 구획에 문구를 나타내기 위해 요소정의를 해준다.
    → unsaved 문구를 별도 구획에 나타내주고, save 이후엔 문구를 제거하도록 구성한다.
let messageBox = document.querySelector('.messageBox');
let indicator = document.createTextNode('UNSAVED');
  • save button에 click event를 부여한다.
    → ※ save button 클릭 이후엔 file save가 진행되는 동시에 unsaved 문구가 사라진다.
    → ※ 세부 logic은 아래에서 자세히 기술.

addEventListener and file create/save as

  • textArea(글자를 쓰는 영역)에서 변화를 감지하는 event를 부여한다(=input event).
  • 변화를 감지하게되면 messageBox 영역에 appendChild해서 indicator(Unsaved 문구)가 나타나도록 설정해준다.
    → ※ appendChild
textArea.addEventListener('input', (e)=>{indicateChangedText(e)});

		function indicateChangedText(e){		
			messageBox.appendChild(indicator);
		}
  • save button을 누른후 file save가 되는 동시에, indicator를 remove하여 unsaved 문구가 사라지도록 구성한다.
    → ※ removeChild
saveButton.addEventListener('click', ()=>{
		downloadFunction(textArea.value, 'file.txt', 'text/plain');
		messageBox.removeChild(indicator);
		})
  • unsaved 문구가 구현되었을때의 화면은 아래와 같다.

5. remind logic

▶ vanillaJS를 통한 file create/save as logic 구현하기

function downloadFunction(content, fileName, fileType){
			const a = document.createElement('a');
			const textFile = new Blob([content], {type: fileType});
		
			a.href = URL.createObjectURL(textFile);
			a.download = fileName;
			a.click();

			URL.revokeObjectURL(a.href);
		}
  • file create, save as logic
    → textFile 정보를 Blob를 통해 객체화한다.
    → 이 textFile은 createObjectURL을 통해 DOM string으로 되었고, 이를 anchor element 정보에 담았다.
    → file download logic을 textFile 정보가 담긴 a element(by href)로 부터 download - click method를 사용하여 구현한다.
    → revokeObjectURL은 메모리에 저장된 URL 정보를 제거해준다.

6. 참조링크

file upload logic(sugar syntax)
https://developer.mozilla.org/ko/docs/Web/API/Blob/Blob

file upload logic(fundamental)
https://robkendal.co.uk/blog/2020-04-17-saving-text-to-client-side-file-using-vanilla-js

about Blob
https://developer.mozilla.org/ko/docs/Web/API/Blob/Blob

활용해야하는 메소드

좋은 웹페이지 즐겨찾기