Как создать возобновляющийся видео-загрузчик в Node.js

Как создать возобновляющийся видео-загрузчик в Node.js

От автора: если вы когда-либо выкладывали сравнительно большой видео-файл, то испытывали это ощущение: закончили уже на 90% и нечаянно обновили страницу – и приходится начинать все снова.

В этом учебнике я продемонстрирую, как сделать видео-загрузчик для своего сайта, умеющий возобновлять прерванную выгрузку, а по ее завершении – генерировать пиктограмму.

скачать исходники

Вступление

Чтобы сделать загрузчик возобновляемым, серверу нужно отследить, какой объем файла уже выгружен, и уметь продолжить с того места, где выгрузка остановилась. Для выполнения этой задачи мы дадим серверу Node.js полный контроль над запросами отдельных блоков данных, а форма HTML будет считывать эти запросы и отсылать серверу необходимую информацию.

Для создания такого обмена применим Socket.io. Если вы никогда не слышали о Socket.io, то это инфраструктура для коммуникации в режиме реального времени между Node.js и веб-страницей HTML – более полно об этом мы вскоре поговорим.
Таков общий замысел; начнем с формы HTML.

Шаг 1: HTML

Я собираюсь сделать HTML простым и ясным; все, что нам нужно – ввод для выбора файла, текстовое поле для названия и кнопка начала выгрузки. Вот необходимый код:

Обратите внимание, что я обернул содержимое в span; этим мы воспользуемся позже для обновления разметки страницы с помощью JavaScript. В этом учебнике я не собираюсь разжевывать весь CSS, а вы, если захотите воспользоваться моим исходным кодом, можете его скачать.

Шаг 2: Заставим его работать

HTML5 еще сравнительно нов, и не поддерживается всеми браузерами. Первое, что нужно сделать – это убедиться, что браузер пользователя поддерживает HTML5 File API и класс FileReader.

Класс FileReader дает возможность открывать и читать части файла и передавать данные на сервер как двоичную строку. Вот JavaScript для детекции контуров:

Вышеприведенный код добавляет кнопке и вводу файла в форму обработчики событий. Функция FileChosen просто устанавливает глобальную переменную файла – чтобы позже мы смогли получить к нему доступ – и заполняет поле ввода названия, чтобы у пользователя была контрольная точка при присвоении файлу имени. Вот функция FileChosen:

Перед написанием функции StartUpload нужно установить Node.js с socket.io; давайте сейчас этим и займемся.

Шаг 3: Сервер Socket.io

Как упоминалось ранее, я применю Socket.io для коммуникации между сервером и файлом HTML. Для закачки Socket.io напишите npm install socket.io в окно терминала (подразумевается, что Node.js вы установили), перейдя в директорию этого проекта. Socket.io работает так: как только сервер или клиент «эмитирует» событие, другая сторона улавливает это событие в виде функции с опцией передачи данных JSON туда и обратно. Для начала создайте пустой файл JavaScript и поместите в него следующий код.

Пять первых строк включают нужные библиотеки, следующая строка передает серверу инструкцию слушать порт 8080, а функция обработчика просто передает содержимое нашего файла HTML пользователю при входе на сайт.

Последние две строки – это обработчик socket.io, и вызываются, когда кто-то соединяется через Socket.io.
Теперь можно вернуться к файлу HTML и определить несколько событий socket.io.

Шаг 4: События Socket.io

Чтобы начать использовать на своей странице Socket.io, сначала нужно соединиться с его библиотекой JavaScript. Делаем это тем же образом, которым мы обратились бы к любой библиотеке: сделайте на нее ссылку в области head. Добавьте на страницу следующее, естественно, перед своими скриптами.

Не беспокойтесь по поводу получения этого файла, так как он генерируется сервером Node.js во время исполнения. Теперь можно написать функцию StartUpload, которую мы присоединили к своей кнопке:

Первая строка соединяет с сервером Socket.io; далее мы создали две переменные для File Reader’а и название файла, так как собираемся получить к ним глобальный доступ. Внутри этой функции мы сначала убедились, что пользователь выбрал файл, и, если он это сделал, создаем FileReader и обновляем DOM с красивым индикатором выполнения.

Метод FileReader’а onload вызывается каждый раз при считывании каких-либо данных; все, что нужно сделать – это эмитировать событие Upload и послать данные на сервер. Наконец, эмитируем событие Start, передавая серверу Node.js название и размер файла.

Теперь вернемся к файлу Node.js и выполним к этим двум событиям обработчики.

Шаг 5: Обработка событий

Вам нужно время от времени очищать буфер, или сервер упадет из-за перегрузки памяти.

События socket.io проходят внутри обработчика, находящегося в последней строке файла Node.js. Первое событие, которое мы выполним – Start, запускаемое при щелчке пользователя по кнопке Upload (Выгрузить).

Ранее я упоминал, что сервер должен контролировать те данные, которые ему нужно получить далее; это позволит продолжать закачку с предыдущей, оставшейся незавершенной. Он делает это, сначала определив, находился ли там не закончивший выгрузку файл с таким названием, и если находился, то продолжит с места, где тот остановился; иначе же начнет все сначала. Мы передадим эти данные в инкрементах по полмегабайта, что выходит по 524288 байтов.

Для отслеживания различных выгрузок, происходящих одновременно, нам нужно добавить переменную для хранения. Вверху своего файла добавьте var Files = {};’ Вот код события Start:

Сначала добавляем в массив Files новый файл с размером, данными и количеством закачанных к этому моменту байтов. Переменная Place хранит, где мы находимся в файле – она по умолчанию ставится на 0, что означает начало. Затем проверяем, существует ли уже файл (т.е. он был уже на середине и остановился), и соответственно обновляем переменные. Новая ли это выкачка или нет, сейчас мы открываем файл для записи в папку Temp/ и эмитируем событие MoreData, чтобы запросить следующую часть данных из файла HTML.

Теперь нужно добавить событие Upload, которое, если вы помните, вызывается каждый раз, когда прочитывается новый блок данных. Вот функция:

Две первые строки этого кода обновляют новыми данными буфер и переменную общего количества закачанных байтов. Нам нужно хранить данные в буфере и сохранять их в инкрементах, чтобы не положить сервер по причине перегрузки памяти; каждые десять мегабайт мы будем сохраняться и чистить буфер.

Первое if-предложение определяет, полностью ли выкачался файл, второе проверяет, достиг ли размер буфера 10 MB и, наконец, мы запрашиваем MoreData, передавая выполнение в процентах и извлекая следующий блок данных.

Теперь можно вернуться к файлу HTML, выполнить событие MoreData и обновить прогресс.

Шаг 6: Отслеживание прогресса

Я создал функцию обновления индикатора выполнения и количества выкачанных на страницу мегабайт. Вдобавок к этому событие More Data считывает блок запрошенных сервером данных и передает их на него.

Чтобы разбить файл на блоки, мы применяем команду File API Slice. Так как File API все еще разрабатывается, нам нужно применить для браузеров Webkit и Mozilla соответственно webkitSlice и mozSlice.

На этой функции загрузчик наконец заканчивается! Все, что нам остается сделать – переместить законченный файл из папки Temp/ и сгенерировать пиктограмму.

Шаг 7: Пиктограмма

Перед генерированием пиктограммы нужно переместить файл из временной папки. Это можно сделать, применив файловые потоки и метод pump. Метод pump принимает потоки read и write и буферизует данные. Вам нужно добавить этот код туда, где в событии Upload я написал ‘Здесь пиктограмма’:

Мы добавили команду разъединиться unlink; так временный файл удалится после окончания его копирования. Теперь перейдем к пиктограмме: для генерации пиктограмм мы применим ffmpeg, потому что он способен обрабатывать множество форматов и его легко установить. На момент написания этого текста хороших модулей ffmpeg нет, поэтому мы применим команду exec, позволяющую нам выполнять терминальные команды изнутри Node.js.

Команда ffmpeg сгенерирует одну пиктограмму на отметке 1:30 и сохранит ее в папку Video/ папка с файлом .jpg. Редактировать время пиктограммы можно, меняя параметр -ss. Как только пиктограмма сгенерирована, мы эмитируем событие Done. Теперь давайте вернемся к HTML-странице.

Шаг 8: Окончание

Событие Done удалит индикатор выполнения и заменит его на изображение-пиктограмму. Так как Node.js не установлен в качестве веб-сервера, вам нужно для загрузки изображения поместить в переменную Path расположение своего сервера (например, Apache).

Выше мы добавили кнопку начала закачки другого файла; все, что она делает – обновляет страницу.

Заключение

Вот и все, что касается загрузчика, и, конечно, можно представить все его возможности при объединении с базой данных и HTML5-плеером! Надеюсь, вам понравился этот учебник! Внизу в разделе комментариев дайте мне знать, что вы о нем думаете.

Автор: Gabriel Manricks

Источник: //net.tutsplus.com/

Редакция: Команда webformyself.

Метки: ,

Похожие статьи:

Комментарии Вконтакте: