FileAPI: Загрузка и обработка файлов
2
Что было
3
Что было
4
Что было
Flash
5
Что было
HTML/JS
6
• Множественный выбор файлов
• Получение информации (название, размер, тип)
• Создание пред-просмотра на клиенте
• Масштабирование, кадрирование и поворот
• Загрузка на сервер + CORS
Требования
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.addEventListener("change", function (){
var files = input.files;
}, false);
</script>
15
HTML5
<input id="file" type="file" multiple />
<script>
var input = document.getByElementId("file");
input.addEventListener("change", function (){
var files = input.files;
}, false);
</script>
16
HTML5
<input id="file" type="file" multiple />
<script>
var input = document.getByElementId("file");
input.addEventListener("change", function (){
var files = input.files;
}, false);
</script>
17
Flash
FLASH
18
Flash
FLASH
19
Flash
FLASH
Flash --> jsFunc([{
id: "346515436346", // уникальный идентификатор
name: "hello-world.png", // название файла
type: "image/png", // mime-type
size: 43325 // рамер
}, {
// etc.
}])
Взаимодействие
flash.cmd("imageTransform", {
id: "346515436346", // идентификатор файла
matrix: { }, // "матрица" трансформации
callback: "__UNIQ_NAME__" // размер
});
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>
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>
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){
if( files.length > 0 ){
// ...
}
});
FileAPI.getInfo(audioFile, function (err, tags){
if( !err ){
var li = document.createElement("li");
li.innerHTML = tags.artist +" – "+ tags.title;
ul.appendChild(li);
}
});
Информация о файле
ПРЕДПРОСМОТР
Предпросмотр
DataURI
Предпросмотр
DataURI
Base64
Предпросмотр
DataURI
Base64
“data:image/png;base64,” + Base64
<img/>
Предпросмотр
DataURI
Base64
“data:image/png;base64,” + Base64
<img/>
Предпросмотр
HTML5
• FileReader.readAsDataURL(file) — позволяет
прочесть содержимое файла как DataURL
• URL.createObjectURL(file) — создает ссылку,
указывающую на файл
Предпросмотр
HTML5
• FileReader.readAsDataURL(file) — позволяет
прочесть содержимое файла как DataURL
• URL.createObjectURL(file) — создает ссылку,
указывающую на файл
• URL.revokeObjectURL(file) — убрать ссылку
34
• crop(x, y, width, height) — кадрирование
• resize(width[, height]) — масштабирование
• rotate(deg) — поворот
• preview(width, height) — кадрирует и масштабирует
• get(callback) — получить итоговое изображение
FileAPI.Image
35
Matrix
{ // параметры фрагмента оригинала
sx: Number,
sy: Number,
sw: Number,
sh: Number,
// требуемые размеры
dw: Number,
dh: Number,
deg: Number
}
36
FileAPI.Image
FileAPI.Image(imageFle)
.crop(300, 300)
.resize(100, 100)
.get(function (err, img){
if( !err ){
images.appendChild(img);
}
})
;
Сжатие
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="foo" value="bar" type="hidden" />
</form>
Загрузка
<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>
Уникальный идентификатор
Загрузка
XMLHttpRequest level 2
FormData
Загрузка
// собираем данные для отправки
var form = new FormData
form.append("foo", "bar");
form.append("attach", file);
// отправояем на сервер
var xhr = new XMLHttpRequest;
xhr.open("POST", "/upload", true);
xhr.send(form)
Загрузка
// собираем данные для отправки
var form = new FormData
form.append("foo", "bar");
form.append("attach", file);
// отправояем на сервер
var xhr = new XMLHttpRequest;
xhr.open("POST", "/upload", true);
xhr.send(form)
Загрузка
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)
});
Загрузка
<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:[^,]+,/, “”);
binaryString = window.atob(base64);
53
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'));
54
Загрузка
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
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){}
});
Загрузка
Загрузка
{
huge: { maxWidth: 800, maxHeight: 600, rotate: 90 },
medium: { width: 320, height: 240, preview: true },
small: { width: 100, height: 120, preview: true }
}
imageTransform:
57
XHR
var xhr = FileAPI.upload({ … });
58
XHR
var xhr = FileAPI.upload({ … });
• status — HTTP status code
• statusText — HTTP status text
• responseText — ответ сервера
• getResponseHeader(name) — получить заголовок ответа сервера
• getAllResponseHeaders() — получить все заголовки
• abort() — отменить загрузку
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, function (over){
if( ever ){
el.classList.add("dropzone_hover");
} else {
el.classList.remove("dropzone_hover");
}
}, function (files){
uploadFiles(files);
});
</script>
4
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
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
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
Drag’n’Drop
function uploadFiles(dropFiles){
FileAPI.upload({
url: "/upload",
files: { attaches: dropFiles },
complete: function (err, xhr){
if( !err ){
// файлы загружены
}
}
});
}
4
Спустя год
• Закрыто более 100 github issue
• GruntJS (JSLint, QUnit + PhantomJS, Uglify)
• Улучшена работа с изображениями
• Добавлена поддержка работы с веб-камерой
• Разработан jQuery plugin для типовых задач
• Улучшена документация (+ примеры)
OVERLAYS
Overlay
FileAPI.Image(imageFile)
.overlay([{
x: 10
, y: 10
, src: "/i/watermark.png"
, rel: FileAPI.Image.RITGHT_BOTTOM
, opacity: 0.85
])
.get(function (err/**String*/, img/**HTMLElement*/)({ /*__*/ })
;
Overlay
var xhr = FileAPI.upload({
url: "...",
files: images,
imageTransform: {
overlay: { /* options */ }
}
});
FILTERS
Filters
FileAPI.Image(imageFile)
.filter(function (canvas, doneFn){
// processing...
doneFn();
})
.get(function (err/**String*/, img/**HTMLElement*/)({
/*__*/
})
;
CamanJS
Filters + CamanJS
FileAPI.Image(imageFile)
.filter("hazyDays")
.get(function (err/**String*/,
img/**HTMLElement*/)({
/*__*/
})
;
WebCam
WebCam
navigator.getUserMedia( constraints, success, error );
— запросить разрешение на использование
микрофона и/или камеры
WebCam
navigator.getUserMedia({ video: true }, function (stream){
var video = document.getElementById("webcam");
var streamSrc = URL.createObjectURL(stream);
video.src = streamUrl;
});
WebCam
navigator.getUserMedia({ video: true }, function (stream){
var video = document.getElementById("webcam");
var streamSrc = URL.createObjectURL(stream);
video.src = streamUrl;
});
WebCam
function onTakeShot(){
var video = document.getElementById("webcam");
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
}
FileAPI.Camera
var el = document.getElementById("webcam");
FileAPI.Camera.publish(el, function (cam){
});
FileAPI.Camera
var el = document.getElementById("webcam");
FileAPI.Camera.publish(el, function (cam){
FileAPI.event.on(btn, "click", function (){
var shot = cam.shot(); // FileAPI.Image instance
FileAPI.upload({ url: "...", files: shot });
});
});
jQuery.FileAPI
• «Одной кнопкой» — выбрать и автоматически загрузить файл
• «Ограничения» — минимальный/максимальный размер как
файла, так и изображения, по ширине и высоте
• «Работа с очередью» — сортировка и фильтрация очереди
загрузки файлов
• «Изображения» — предпросмотр, поворот и кадрирование
• «Интерфейс» — гибкая и прозрачная настройка интерфейса
• А также Drag’n’Drop и WebCam
jQuery.FileAPI
jQuery.FileAPI
jQuery.FileAPI
jQuery.FileAPI
jQuery.FileAPI
Top Related