이 글은 XHR progress and rich file upload feedback에 대한 번역 및 편집본입니다.
오늘날 웹에서는 파일 업로드를 할 때 리치 인터페이스를 제공하는 위젯에 대한 공통적인 제약점을 가지고 있다. 많은 사이트들이 Flash 혹은 데스크탑 어플리케이션을 이용하여 파일을 업로드할 때 보다 나은 사용자 경험을 제공하고 있다.
Firefox 3.5에서는 더 나은 프로그레스 표시바를 만들 수 있도록 이러한 격차 중 하나를 중개해준다. 많은 개발자들은 파일 업로드를 할 때 Firefox File 객체(nsIDOMFile)와 XMLHttpRequest를 같이 사용할 수 있다는 사실을 모르고 있다. 이 데모에서는 사용자에게 업로드 상태를 예측할 수 있게끔 피드백을 주는 것 뿐만 아니라, 여러개의 파일을 동시에 빠르고 쉽게 올릴 수 있는 위젯에 대해 설명을 한다.
Progress Indicator
현재 어플리케이션이 요청한 작업을 할 수 없거나 현재 진행 중인 작업이 완료될 것 같으면 사용자에게 피드백을 주는 것이 좋다. 피드백을 주는 대표적인 두가지 방식으로는 다음과 같이 있다.
* 가늠할 수 없는 프로그레스 – 어떤 작업이 방금 수행됬습니다.
* 가늠 할 수 있는 프로그레스 – ‘40% 완료 되었습니다.’, ‘42% 완료 되었습니다’ 등등..
데모 Deterministicasaidwhat?
파일 업로드/다운로드 상태의 프로그레스 바를 띄어주는 간단한 페이지를 만들었다.
데모는 mozilla.pettay.fi 에 호스팅되어 있고, Firefox3.5 beta4 혹은 그 이후 버전에서 동작한다. 여기서는 여러 개의 파일이 따로 폼을 등록하거나 현재 페이지를 벗어나지 않고 어떻게 동시에 업로드될 수 있는지 보여준다. 각각의 파일이 업로드 / 다운로드될 때 현재 속도, 완료률(%) 그리고 전송된 바이트 크기를 보여준다. 이제 이 페이지에서 사용했던 코드 중 몇몇 부분을 살펴보자. “데모(http://mozilla.pettay.fi/xhr_upload/xhr_file_upload_demo_with_speed.html)” 를 클릭하여 데모 페이지로 이동한 후 페이지 소스 보기를 통하여 전체 코드를 살펴보자.
이 페이지에는 2개의 HTML 태그가 있다. 하나는 type=”file”이고 다른 하나는 type=”button” 이다. 폼은 버튼에 onclick 핸들러를 추가하지 않는 이상 전송되지 않는다.
<input type="file" id="file"> <input type="button" onclick="startXHR();" value="Upload file using XHR">
startXHR 함수에서 XMLHttpRequest를 만들고 새로이 ‘프로그레스’ 이벤트를 받기 위해 XHR 요청에 이벤트 핸들러를 등록했다. ProgressEvent의 lengthComputable 프로퍼티를 통해 가늠할 수 있는 프로그레스 인지 아니면 가늠할 수 없는 프로그레스인지 알 수 있게된다. 또한 파일의 전체 크기와 업로드된 바이트 크기를 알 수 있다.
var xhr = new XMLHttpRequest(); xhr.onprogress = function(evt) { if (evt.lengthComputable) { evt.target.curLoad = evt.loaded; evt.target.log.parentNode.parentNode.previousSibling.textContent = Number(evt.loaded/k).toFixed() + "/"+ Number(evt.total/k).toFixed() + "kB"; } if (evt.lengthComputable) { var loaded = (evt.loaded / evt.total); if (loaded < 1) { var newW = loaded * width; if (newW < 10) newW = 10; evt.target.log.style.width = newW + "px"; } } };
이제 우리는 전송을 할 데이터가 필요하다. input의 id를 통해 바로 전송할 파일을 가져왔다.
var files = document.getElementById("file").files; if (files) { var file = files.item(0); xhr.sendAsBinary(file.getAsBinary());
마지막으로 실제 요청을 보내 보자.
xhr.open("POST", "cgi-bin/posthandler.pl"); xhr.overrideMimeType('text/plain; charset=x-user-defined-binary'); xhr.sendAsBinary(file.getAsBinary());
이 메소드들은 xhr.upload.onprogress와도 동작할 것이다.
XMLHttpRequest 객체의 sendAsBinary 메소드와 File 객체의 getAsBinary 메소드를 사용한 것을 눈여겨 보자. Firefox 3 에 와서는 클라이언트 쪽에서 폼 전송을 통하지 않고도 파일을 전송할 수 있게
되었다. 기존의 input 과 폼 전송보다 이를 사용하는 것이 더 유용하다. 뿐만 아니라 다음 번 W3C 표준으로 채택되었다.
nsIDOMFile이 제공하는 연관된 메소드로는 자르고, 표시하는데 편리한 DOMString을 리턴해주는 getAsText 메소드가 있다.
데모에는 사용되지 않았지만, nsLDOMFile에 관한 예제 하나를 보여준다.
file.getAsText("utf8");
위에서 보여준 파일 업로드에 관한 예제는 요지만 보여준 코드이다. “데모에서 전체 코드”(링크 : http://mozilla.pettay.fi/xhr_upload/xhr_file_upload_demo_with_speed.html) 를 살펴보길 바란다.
Feedback In User Interfaces
시스템이 피드백을 주면 사용자가 지각하는데 큰 도움을 준다. 우리는 항상 어떤 작업이 얼마나 걸릴지 판단하기 힘들다. 따라서 최소한으로 가늠할 수 없는 프로그레스 바라도 표시를 해주어야 한다.
파일을 업로드 / 다운로드 하는 동안 (서버가 Content-Length를 주었다는 가정 하에) 우리는 확실히 전체 바이트 크기를 알고 있어야 한다. Firefox 3.5의 ProgressEvents 는 프로그레스 이벤트를 추가하여 정확한 업로드/다운로드 프로그레스 상태를 볼 수 있도록 해준다.
전통적으로 XMLHttpRequest로는 가늠할 수 있는 프로그레스를 만들기는 어렵다. 이론적으로 콜백으로 상태 코드와 업데이트 된 문자들을 받아와 표시를 했는데, 그리 효율적이지 못하다. 과거에는 가늠할 수 있는 프로그레스 바가 중요하다면, 매초마다 상태값을 받아오는 XHR 요청을 보내야만 했다.
Enter Progress Events
W3C에서 Firefox 3.5에 포함된 Progress Events 1.0 의 초안을 작성하고 있다. Firefox는 새로운 DOM ~ . 그 외 error, abort 그리고 load 같은 존재했던 다른 이벤트들도 포함됬다.
이 이벤트들은 업로드와 다운로드 때 모두 가능하다. 프로그레스 이벤트는 다음과 같은 프로퍼티를 제공한다.
* lengthComputable – 요청의 크기를 알 수 있는지 여부
* loaded – 전송된 바이트의 크기
* total – 요청의 전체 바이트 크기
The Contract
프로그레스 이벤트의 프로퍼티들을 살펴보면, 여기에 적용된 룰들이 있다.
* lengthComputable이 false면, total 프로퍼티 값은 0가 된다.
* loadstart 이벤트는 항상 한 번만 호출된다.
* progress 이벤트는 loadstart 이벤트가 호출된 이후 0번 혹은 여러번 호출된다.
“이것이 다입니다”(링크 : http://mozilla.pettay.fi/xhr_upload/xhr_file_upload_demo_with_speed.html). Firefox 3.5 를 이용하여 보다 향상된 파일 업로드를 구현해 보세요.
댓글이 없습니다.