константин лебедев

69

Upload: kuchinskaya

Post on 22-Jun-2015

3.326 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: константин лебедев
Page 2: константин лебедев

FileAPI: Загрузка и обработка файлов

Константин Лебедевhttps://github.com/mailru/FileAPI

Page 3: константин лебедев

3

Что было

Page 4: константин лебедев

4

Что было

Page 5: константин лебедев

5

Что было

Flash

Page 6: константин лебедев

6

Что было

HTML/JS

Page 7: константин лебедев

7

• Множественный выбор файлов

• Получение информации (название, размер, тип)

• Создание пред-просмотра на клиенте

• Масштабирование, кадрирование и поворот

• Загрузка на сервер + CORS

Требования

Page 8: константин лебедев

8

• Не зависеть от вёрстки

• Никакой бизнес-логики

• Расширяемость

• Самодостаточность

Требования

Page 9: константин лебедев
Page 10: константин лебедев

Error #2038

10%

Page 11: константин лебедев

Error #2038

5%

Page 12: константин лебедев

12

Поддержка

• Chrome 10+• FireFox 3.6+• Opera 11.1+• Safari 5.4+

Page 13: константин лебедев

13

Page 14: константин лебедев

14

ПОЛУЧЕНИЕ СПИСКАФАЙЛОВ

Page 15: константин лебедев

15

HTML5

<input id="file" type="file" multiple /><script>

var input = document.getByElementId("file");input.addEventListener("change", function (){

var files = input.files;}, false);

</script>

Page 16: константин лебедев

16

HTML5

<input id="file" type="file" multiple /><script>

var input = document.getByElementId("file");input.addEventListener("change", function (){

var files = input.files;}, false);

</script>

Page 17: константин лебедев

17

HTML5

<input id="file" type="file" multiple /><script>

var input = document.getByElementId("file");input.addEventListener("change", function (){

var files = input.files;}, false);

</script>

Page 18: константин лебедев

18

Flash

FLASH

Page 19: константин лебедев

19

Flash

FLASH

Page 20: константин лебедев

20

Flash

FLASH

Flash --> jsFunc([{id: "346515436346", // уникальный идентификаторname: "hello-world.png", // название файлаtype: "image/png", // mime-typesize: 43325 // рамер

}, { // etc.}])

Page 21: константин лебедев

Взаимодействие

flash.cmd("imageTransform", {id: "346515436346", // идентификатор файлаmatrix: { }, // "матрица" трансформацииcallback: "__UNIQ_NAME__" // размер

});

Page 22: константин лебедев

22

API

<span class="js-fileapi-wrapper" style="position: relative"><input id="file" type="file" multiple />

</span><script>

var input = document.getByElementId("file");FileAPI.event.on(input, "change", function (){

var files = FileAPI.getFiles(input);}, false);

</script>

Page 23: константин лебедев

23

API

<span class="js-fileapi-wrapper" style="position: relative"><input id="file" type="file" multiple />

</span><script>

var input = document.getByElementId("file");FileAPI.event.on(input, "change", function (evt){

var files = FileAPI.getFiles(evt);}, false);

</script>

Page 24: константин лебедев

24

ФИЛЬТРАЦИЯ

Page 25: константин лебедев

FileReader

• readAsDataURL(file)

• readAsBinaryString(file)

• readAsArrayBuffer(file)

• readAsText(file[, encoding])

Page 26: константин лебедев

26

Фильтрация

FileAPI.filterFiles(files, function (file, info){

return file.size < 10 * FileAPI.MB;

}, function (files, ignore){

if( files.length > 0 ){

// ...

}

});

Page 27: константин лебедев

FileAPI.addInfoReader(/^audio/, function (file, callback){

// собираем нужную информацию

// и возвращаем её

callback(

false, // или текст ошибки

{ artist: "...", album: "...", title: "...", ... }

);

});

Информация о файле

Page 28: константин лебедев

FileAPI.getInfo(audioFile, function (err, tags){

if( !err ){

var li = document.createElement("li");

li.innerHTML = tags.artist +" – "+ tags.title;

ul.appendChild(li);

}

});

Информация о файле

Page 29: константин лебедев

ПРЕДПРОСМОТР

Page 30: константин лебедев

Предпросмотр

DataURI

Page 31: константин лебедев

Предпросмотр

DataURI

Base64

Page 32: константин лебедев

Предпросмотр

DataURI

Base64

“data:image/png;base64,” + Base64

<img/>

Page 33: константин лебедев

Предпросмотр

DataURI

Base64

“data:image/png;base64,” + Base64

Base64

<img/>

Page 34: константин лебедев

Предпросмотр

HTML5

• FileReader.readAsDataURL(file) — позволяет

прочесть содержимое файла как DataURL

• URL.createObjectURL(file) — создает ссылку,

указывающую на файл

Page 35: константин лебедев

Предпросмотр

HTML5

• FileReader.readAsDataURL(file) — позволяет

прочесть содержимое файла как DataURL

• URL.createObjectURL(file) — создает ссылку,

указывающую на файл

• URL.revokeObjectURL(file) — убрать ссылку

Page 36: константин лебедев

36

• crop(x, y, width, height) — кадрирование

• resize(width[, height]) — масштабирование

• rotate(deg) — поворот

• preview(width, height) — кадрирует и масштабирует

• get(callback) — получить итоговое изображение

FileAPI.Image

Page 37: константин лебедев

37

Matrix

{ // параметры фрагмента оригинала sx: Number,sy: Number,sw: Number,sh: Number,

// требуемые размеры

dw: Number,dh: Number,deg: Number

}

Page 38: константин лебедев

38

FileAPI.Image

FileAPI.Image(imageFle).crop(300, 300).resize(100, 100).get(function (err, img){

if( !err ){images.appendChild(img);

}})

;

Page 39: константин лебедев

Сжатие

5197х4987

Page 40: константин лебедев

Сжатие

Page 41: константин лебедев

Сжатие

5197х4987 2598х2493

Page 42: константин лебедев

Сжатие x 2

5197х4987 2598х2493 1299х1246

Page 43: константин лебедев

Сжатие x 5

5197х4987 2598х2493 1299х1246

100х100

Page 44: константин лебедев

Сжатие

Серия

Page 45: константин лебедев

ЗАГРУЗКА ФАЙЛОВ

Page 46: константин лебедев

• Без обновления страницы

• Процесс загрузки

• Получить ответ от сервера

Требования

Page 47: константин лебедев

Загрузка

<form action="/upload" method="post" enctype="multipart/form-data">

<input name="files" type="file" /><input name="foo" value="bar" type="hidden" />

</form>

Page 48: константин лебедев

Загрузка

<form target="__UNIQ__" action="/upload" method="post" enctype="multipart/form-data">

<iframe name="__UNIQ__"></iframe><input name="files" type="file" /><input name="foo" value="bar" type="hidden" />

</form>

Уникальный идентификатор

Page 49: константин лебедев

Загрузка

XMLHttpRequest level 2

FormData

Page 50: константин лебедев

Загрузка

// собираем данные для отправки

var form = new FormDataform.append("foo", "bar");form.append("attach", file);

// отправояем на сервер

var xhr = new XMLHttpRequest;xhr.open("POST", "/upload", true);xhr.send(form)

Page 51: константин лебедев

Загрузка

// собираем данные для отправки

var form = new FormDataform.append("foo", "bar");form.append("attach", file);

// отправляем на сервер

var xhr = new XMLHttpRequest;xhr.open("POST", "/upload", true);xhr.send(form)

Page 52: константин лебедев

ЗагрузкаcanvasToBlob(canvas, function (blob){

// собираем данные для отправки

var form = new FormDataform.append("foo", "bar");form.append("attach", blob, "filename.png");

// отправляем на сервер

var xhr = new XMLHttpRequest;xhr.open("POST", "/upload", true);xhr.send(form)

});

Page 53: константин лебедев

Загрузка

<cavnas/> DataURL

dataURL = canvas.toDataURL(“image/png”);

Page 54: константин лебедев

Загрузка

<cavnas/> DataURL Base64

dataURL = canvas.toDataURL(“image/png”);

base64 = dataURL.replace(/^data:[^,]+,/, “”);

Page 55: константин лебедев

Загрузка

<cavnas/> DataURL Base64

BinaryString

dataURL = canvas.toDataURL(“image/png”);

base64 = dataURL.replace(/^data:[^,]+,/, “”);

binaryString = window.atob(base64);

Page 56: константин лебедев

56

Multipart

var uniq = '1234567890';var xhr = new XMLHttpRequest;xhr.open('POST', '/upload', true);xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=_'+uniq);xhr.sendAsBinary([ '--_'+ uniq, 'Content-Disposition: form-data; name="my-file"; filename="hello-world.png"', 'Content-Type: image/png', '', binaryString, '--_'+ uniq +'--'].join('\r\n'));

Page 57: константин лебедев

57

Загрузка

var xhr = FileAPI.upload({ url: '/upload', data: { foo: 'bar' }, headers: { 'Session-Id': '...' }, files: { images: imageFiles, others: otherFiles }, imageTransform: { maxWidth: 1024, maxHeight: 768 }, upload: function (xhr){}, progress: function (event, file){}, complete: function (err, xhr, file){}, fileupload: function (file, xhr){}, fileprogress: function (event, file){}, filecomplete: function (err, xhr, file){}});

Page 58: константин лебедев

58

var xhr = FileAPI.upload({ url: '/upload', data: { foo: 'bar' }, headers: { 'Session-Id': '...' }, files: { images: imageFiles, others: otherFiles }, imageTransform: { maxWidth: 1024, maxHeight: 768 }, upload: function (xhr){}, progress: function (event, file){}, complete: function (err, xhr, file){}, fileupload: function (file, xhr){}, fileprogress: function (event, file){}, filecomplete: function (err, xhr, file){}});

Загрузка

Page 59: константин лебедев

Загрузка

{

huge: { maxWidth: 800, maxHeight: 600, rotate: 90 },

medium: { width: 320, height: 240, preview: true },

small: { width: 100, height: 120, preview: true }

}

imageTransform:

Page 60: константин лебедев

60

XHR

var xhr = FileAPI.upload({ … });

Page 61: константин лебедев

61

XHR

var xhr = FileAPI.upload({ … });

• status — HTTP status code

• statusText — HTTP status text

• responseText — ответ сервера

• getResponseHeader(name) — получить заголовок ответа сервера

• getAllResponseHeaders() — получить все заголовки

• abort() — отменить загрузку

Page 62: константин лебедев

Drag’n’Drop

Перетащите файлы сюда

<div class="dropzone"></div>

Page 63: константин лебедев

Drag’n’Drop

4

<div class="dropzone dropzone_hover"></div>

Page 64: константин лебедев

Drag’n’Drop<div id="el" class="dropzone"></div><script> var el = document.getElementById("el"); FileAPI.event.dnd(el, function (over){ if( ever ){ el.classList.add("dropzone_hover"); } else { el.classList.remove("dropzone_hover"); } }, function (files){ uploadFiles(files); }); </script>

4

Page 65: константин лебедев

Drag’n’Drop<div id="el" class="dropzone"></div><script> var el = document.getElementById("el");

FileAPI.event.dnd(el, function (over){ if( ever ){ el.classList.add("dropzone_hover"); } else { el.classList.remove("dropzone_hover"); } }, function (files){ uploadFiles(files); }); </script>

4

Page 66: константин лебедев

Drag’n’Drop<div id="el" class="dropzone"></div><script> var el = document.getElementById("el");

FileAPI.event.dnd(el, function (over){ if( ever ){ el.classList.add("dropzone_hover"); } else { el.classList.remove("dropzone_hover"); } }, function (files){ uploadFiles(files); }); </script>

4

Page 67: константин лебедев

Drag’n’Drop<div id="el" class="dropzone"></div><script> var el = document.getElementById("el");

FileAPI.event.dnd(el, function (over){ if( ever ){ el.classList.add("dropzone_hover"); } else { el.classList.remove("dropzone_hover"); } }, function (files){ uploadFiles(files); }); </script>

4

Page 68: константин лебедев

Drag’n’Drop

function uploadFiles(dropFiles){ FileAPI.upload({ url: "/upload", files: { attaches: dropFiles }, complete: function (err, xhr){ if( !err ){ // файлы загружены } } }); }

4

Page 69: константин лебедев

Константин ЛебедевJavaScript архитектор[email protected]

https://github.com/mailru/FileAPI