FileAPI: Загрузка и обработка файлов
Константин Лебедев
https://github.com/mailru/FileAPI
2
Что было
3
Что было
4
Что было
Flash
5
Что было
HTML/JS
6
• Множественный выбор файлов
• Получение информации (название, размер, тип)
• Создание пред-просмотра на клиенте
• Масшт...
7
• Не зависеть от вёрстки
• Никакой бизнес-логики
• Расширяемость
• Самодостаточность
Требования
Error #2038
10%
Error #2038
5%
11
Поддержка
• Chrome 10+
• FireFox 3.6+
• Opera 11.1+
• Safari 5.4+
12
13
ПОЛУЧЕНИЕ СПИСКА
ФАЙЛОВ
14
HTML5
<input id="file" type="file" multiple />
<script>
var input = document.getByElementId("file");
input.addEventListene...
15
HTML5
<input id="file" type="file" multiple />
<script>
var input = document.getByElementId("file");
input.addEventListene...
16
HTML5
<input id="file" type="file" multiple />
<script>
var input = document.getByElementId("file");
input.addEventListene...
17
Flash
FLASH
18
Flash
FLASH
19
Flash
FLASH
Flash --> jsFunc([{
id: "346515436346", // уникальный идентификатор
name: "hello-world.png", // название фа...
Взаимодействие
flash.cmd("imageTransform", {
id: "346515436346", // идентификатор файла
matrix: { }, // "матрица" трансформ...
21
API
<span class="js-fileapi-wrapper" style="position: relative">
<input id="file" type="file" multiple />
</span>
<script>...
22
API
<span class="js-fileapi-wrapper" style="position: relative">
<input id="file" type="file" multiple />
</span>
<script>...
23
ФИЛЬТРАЦИЯ
FileReader
• readAsDataURL(file)
• readAsArrayBuffer(file)
• readAsText(file[, encoding])
25
Фильтрация
FileAPI.filterFiles(files, function (file, info){
return file.size < 10 * FileAPI.MB;
}, function (files, ignore)...
FileAPI.addInfoReader(/^audio/, function (file, callback){
// собираем нужную информацию
// и возвращаем её
callback(
false...
FileAPI.getInfo(audioFile, function (err, tags){
if( !err ){
var li = document.createElement("li");
li.innerHTML = tags.ar...
ПРЕДПРОСМОТР
Предпросмотр
DataURI
Предпросмотр
DataURI
Base64
Предпросмотр
DataURI
Base64
“data:image/png;base64,” +
Base64
<img/>
Предпросмотр
DataURI
Base64
“data:image/png;base64,” +
Base64
Base64
<img/>
Предпросмотр
HTML5
• FileReader.readAsDataURL(file) — позволяет
прочесть содержимое файла как DataURL
• URL.createObjectUR...
Предпросмотр
HTML5
• FileReader.readAsDataURL(file) — позволяет
прочесть содержимое файла как DataURL
• URL.createObjectUR...
35
• crop(x, y, width, height) — кадрирование
• resize(width[, height]) — масштабирование
• rotate(deg) — поворот
• previe...
36
Matrix
{ // параметры фрагмента оригинала
sx: Number,
sy: Number,
sw: Number,
sh: Number,
// требуемые размеры
dw: Numb...
37
FileAPI.Image
FileAPI.Image(imageFle)
.crop(300, 300)
.resize(100, 100)
.get(function (err, img){
if( !err ){
images.ap...
Сжатие
5197х4987
Сжатие
Сжатие
5197х4987 2598х2493
Сжатие x 2
5197х4987 2598х2493 1299х1246
Сжатие x 5
5197х4987 2598х2493 1299х1246
100х100
…
Сжатие
Серия
ЗАГРУЗКА ФАЙЛОВ
Загрузка
<form
action="/upload"
method="post"
enctype="multipart/form-data">
<input name="files" type="file" />
<input name=...
Загрузка
<form
target="__UNIQ__"
action="/upload"
method="post"
enctype="multipart/form-data">
<iframe name="__UNIQ__"></i...
Загрузка
XMLHttpRequest level 2
FormData
Загрузка
// собираем данные для отправки
var form = new FormData
form.append("foo", "bar");
form.append("attach", file);
//...
Загрузка
// собираем данные для отправки
var form = new FormData
form.append("foo", "bar");
form.append("attach", file);
//...
Загрузка
canvasToBlob(canvas, function (blob){
// собираем данные для отправки
var form = new FormData
form.append("foo", ...
Загрузка
<cavnas/> DataURL
dataURL = canvas.toDataURL(“image/png”);
Загрузка
<cavnas/> DataURL Base64
dataURL = canvas.toDataURL(“image/png”);
base64 = dataURL.replace(/^data:[^,]+,/, “”);
Загрузка
<cavnas/> DataURL Base64
BinaryString
dataURL = canvas.toDataURL(“image/png”);
base64 = dataURL.replace(/^data:[^...
54
Multipart
var uniq = '1234567890';
var xhr = new XMLHttpRequest;
xhr.open('POST', '/upload', true);
xhr.setRequestHeade...
55
Загрузка
var xhr = FileAPI.upload({
url: '/upload',
data: { foo: 'bar' },
headers: { 'Session-Id': '...' },
files: { ima...
56
var xhr = FileAPI.upload({
url: '/upload',
data: { foo: 'bar' },
headers: { 'Session-Id': '...' },
files: { images: imag...
Загрузка
{
huge: { maxWidth: 800, maxHeight: 600, rotate: 90 },
medium: { width: 320, height: 240, preview: true },
small:...
58
XHR
var xhr = FileAPI.upload({ … });
59
XHR
var xhr = FileAPI.upload({ … });
• status — HTTP status code
• statusText — HTTP status text
• responseText — ответ...
Drag’n’Drop
Перетащите файлы сюда
<div class="dropzone"></div>
Drag’n’Drop
4
<div class="dropzone dropzone_hover"></div>
Drag’n’Drop
<div id="el" class="dropzone"></div>
<script>
var el = document.getElementById("el");
FileAPI.event.dnd(el, fu...
Drag’n’Drop
<div id="el" class="dropzone"></div>
<script>
var el = document.getElementById("el");
FileAPI.event.dnd(el, fu...
Drag’n’Drop
<div id="el" class="dropzone"></div>
<script>
var el = document.getElementById("el");
FileAPI.event.dnd(el, fu...
Drag’n’Drop
<div id="el" class="dropzone"></div>
<script>
var el = document.getElementById("el");
FileAPI.event.dnd(el, fu...
Drag’n’Drop
function uploadFiles(dropFiles){
FileAPI.upload({
url: "/upload",
files: { attaches: dropFiles },
complete: fun...
Константин Лебедев
JavaScript архитектор
k.lebedev@corp.mail.ru
https://github.com/mailru/FileAPI
FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиенте и их загрузка на сервер
Upcoming SlideShare
Loading in …5
×

FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиенте и их загрузка на сервер

1,856 views

Published on

История появления open source библиотеки для работы с файлами. Создание предпросмотра изображений на клиенте. Чтение файлов (exif, id3 и т.п.), загрузка результата на сервер. Всё это работает даже в IE6.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,856
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
9
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

FrontTalks: Константин Лебедев (Mail.ru), File API: обработка файлов на клиенте и их загрузка на сервер

  1. 1. FileAPI: Загрузка и обработка файлов Константин Лебедев https://github.com/mailru/FileAPI
  2. 2. 2 Что было
  3. 3. 3 Что было
  4. 4. 4 Что было Flash
  5. 5. 5 Что было HTML/JS
  6. 6. 6 • Множественный выбор файлов • Получение информации (название, размер, тип) • Создание пред-просмотра на клиенте • Масштабирование, кадрирование и поворот • Загрузка на сервер + CORS Требования
  7. 7. 7 • Не зависеть от вёрстки • Никакой бизнес-логики • Расширяемость • Самодостаточность Требования
  8. 8. Error #2038 10%
  9. 9. Error #2038 5%
  10. 10. 11 Поддержка • Chrome 10+ • FireFox 3.6+ • Opera 11.1+ • Safari 5.4+
  11. 11. 12
  12. 12. 13 ПОЛУЧЕНИЕ СПИСКА ФАЙЛОВ
  13. 13. 14 HTML5 <input id="file" type="file" multiple /> <script> var input = document.getByElementId("file"); input.addEventListener("change", function (){ var files = input.files; }, false); </script>
  14. 14. 15 HTML5 <input id="file" type="file" multiple /> <script> var input = document.getByElementId("file"); input.addEventListener("change", function (){ var files = input.files; }, false); </script>
  15. 15. 16 HTML5 <input id="file" type="file" multiple /> <script> var input = document.getByElementId("file"); input.addEventListener("change", function (){ var files = input.files; }, false); </script>
  16. 16. 17 Flash FLASH
  17. 17. 18 Flash FLASH
  18. 18. 19 Flash FLASH Flash --> jsFunc([{ id: "346515436346", // уникальный идентификатор name: "hello-world.png", // название файла type: "image/png", // mime-type size: 43325 // рамер }, { // etc.
  19. 19. Взаимодействие flash.cmd("imageTransform", { id: "346515436346", // идентификатор файла matrix: { }, // "матрица" трансформации callback: "__UNIQ_NAME__" // размер });
  20. 20. 21 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); }); </script>
  21. 21. 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 (evt){ var files = FileAPI.getFiles(evt); }); </script>
  22. 22. 23 ФИЛЬТРАЦИЯ
  23. 23. FileReader • readAsDataURL(file) • readAsArrayBuffer(file) • readAsText(file[, encoding])
  24. 24. 25 Фильтрация FileAPI.filterFiles(files, function (file, info){ return file.size < 10 * FileAPI.MB; }, function (files, ignore){ if( files.length > 0 ){ // ... } });
  25. 25. FileAPI.addInfoReader(/^audio/, function (file, callback){ // собираем нужную информацию // и возвращаем её callback( false, // или текст ошибки { artist: "...", album: "...", title: "...", ... } ); }); Информация о файле
  26. 26. FileAPI.getInfo(audioFile, function (err, tags){ if( !err ){ var li = document.createElement("li"); li.innerHTML = tags.artist +" – "+ tags.title; ul.appendChild(li); } }); Информация о файле
  27. 27. ПРЕДПРОСМОТР
  28. 28. Предпросмотр DataURI
  29. 29. Предпросмотр DataURI Base64
  30. 30. Предпросмотр DataURI Base64 “data:image/png;base64,” + Base64 <img/>
  31. 31. Предпросмотр DataURI Base64 “data:image/png;base64,” + Base64 Base64 <img/>
  32. 32. Предпросмотр HTML5 • FileReader.readAsDataURL(file) — позволяет прочесть содержимое файла как DataURL • URL.createObjectURL(file) — создает ссылку, указывающую на файл
  33. 33. Предпросмотр HTML5 • FileReader.readAsDataURL(file) — позволяет прочесть содержимое файла как DataURL • URL.createObjectURL(file) — создает ссылку, указывающую на файл • URL.revokeObjectURL(file) — убрать ссылку
  34. 34. 35 • crop(x, y, width, height) — кадрирование • resize(width[, height]) — масштабирование • rotate(deg) — поворот • preview(width, height) — кадрирует и масштабирует • get(callback) — получить итоговое изображение FileAPI.Image
  35. 35. 36 Matrix { // параметры фрагмента оригинала sx: Number, sy: Number, sw: Number, sh: Number, // требуемые размеры dw: Number, dh: Number, deg: Number }
  36. 36. 37 FileAPI.Image FileAPI.Image(imageFle) .crop(300, 300) .resize(100, 100) .get(function (err, img){ if( !err ){ images.appendChild(img); } }) ;
  37. 37. Сжатие 5197х4987
  38. 38. Сжатие
  39. 39. Сжатие 5197х4987 2598х2493
  40. 40. Сжатие x 2 5197х4987 2598х2493 1299х1246
  41. 41. Сжатие x 5 5197х4987 2598х2493 1299х1246 100х100 …
  42. 42. Сжатие Серия
  43. 43. ЗАГРУЗКА ФАЙЛОВ
  44. 44. Загрузка <form action="/upload" method="post" enctype="multipart/form-data"> <input name="files" type="file" /> <input name="foo" value="bar" type="hidden" /> </form>
  45. 45. Загрузка <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> Уникальный идентификатор
  46. 46. Загрузка XMLHttpRequest level 2 FormData
  47. 47. Загрузка // собираем данные для отправки var form = new FormData form.append("foo", "bar"); form.append("attach", file); // отправояем на сервер var xhr = new XMLHttpRequest; xhr.open("POST", "/upload", true); xhr.send(form)
  48. 48. Загрузка // собираем данные для отправки var form = new FormData form.append("foo", "bar"); form.append("attach", file); // отправояем на сервер var xhr = new XMLHttpRequest; xhr.open("POST", "/upload", true); xhr.send(form)
  49. 49. Загрузка canvasToBlob(canvas, function (blob){ // собираем данные для отправки var form = new FormData form.append("foo", "bar"); form.append("attach", blob, "filename.png"); // отправляем на сервер var xhr = new XMLHttpRequest; xhr.open("POST", "/upload", true); xhr.send(form) });
  50. 50. Загрузка <cavnas/> DataURL dataURL = canvas.toDataURL(“image/png”);
  51. 51. Загрузка <cavnas/> DataURL Base64 dataURL = canvas.toDataURL(“image/png”); base64 = dataURL.replace(/^data:[^,]+,/, “”);
  52. 52. Загрузка <cavnas/> DataURL Base64 BinaryString dataURL = canvas.toDataURL(“image/png”); base64 = dataURL.replace(/^data:[^,]+,/, “”); binaryString = window.atob(base64);
  53. 53. 54 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('rn'));
  54. 54. 55 Загрузка 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){} });
  55. 55. 56 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){} }); Загрузка
  56. 56. Загрузка { huge: { maxWidth: 800, maxHeight: 600, rotate: 90 }, medium: { width: 320, height: 240, preview: true }, small: { width: 100, height: 120, preview: true } } imageTransform:
  57. 57. 58 XHR var xhr = FileAPI.upload({ … });
  58. 58. 59 XHR var xhr = FileAPI.upload({ … }); • status — HTTP status code • statusText — HTTP status text • responseText — ответ сервера • getResponseHeader(name) — получить заголовок ответа сервера • getAllResponseHeaders() — получить все заголовки • abort() — отменить загрузку
  59. 59. Drag’n’Drop Перетащите файлы сюда <div class="dropzone"></div>
  60. 60. Drag’n’Drop 4 <div class="dropzone dropzone_hover"></div>
  61. 61. 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
  62. 62. 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
  63. 63. 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
  64. 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
  65. 65. Drag’n’Drop function uploadFiles(dropFiles){ FileAPI.upload({ url: "/upload", files: { attaches: dropFiles }, complete: function (err, xhr){ if( !err ){ // файлы загружены } } }); } 4
  66. 66. Константин Лебедев JavaScript архитектор k.lebedev@corp.mail.ru https://github.com/mailru/FileAPI

×