Модуль предназначен для упрощения загрузки файлов на сервер из браузера. Кроме одновременной закачки нескольких файлов из очереди он умеет опционально обрабатывать изображения на клиенте:
- сохраняющее пропорции авто-масштабирование,
- поворот в соответствии с данными EXIF (для JPEG),
- вырезание EXIF из результирующего файла.
В этом случае изображение принудительно конвертируется в JPEG или WEBP.
Внимание! Формат WEBP на данный момент поддерживается только в броузере Google Chrome.
Класс имеет развитую систему сообщений через коллбэки, что позволяет вынести часть логики (проверку типов файлов, размеров, блокировки закачки дубликатов и т.д.) в вызывающий код. Например, это позволяет гибко управлять отбором файлов, отображением сообщений и т.д.
Такой подход позволяет создавать компоненты-обертки, которые инкапсулируют часть работы. Например так можно легко реализовать в компоненте перетаскивание файлов из проводника или отображение иконок файлов с превьюшками и/или указанием состояния и прогресса закачки каждого файла.
Внимание! Все загружаемые файлы передаются в виде base64-строк, что примерно на 30% увеличивает объем передаваемого трафика.
Данный класс хранит данные закачиваемого файла.
- STATUS_PENDING - статус файла - ожидание закачки
- STATUS_UPLOADING - статус файла - закачивается
- STATUS_SUCESS - статус файла - успешно закачан
- STATUS_ERROR - статус файла - произошла ошибка
-
guid - уникальный идентификатор задачи (пример: ' a8e9034e-ce4b-4329-a734-80252fcc89d4'). Если не указан, то будет создан автоматически
-
origFileName - оригинальное имя файла (без расширения)
-
origFileExt - оригинальное расширение файла
-
origMime - оригинальный mime-тип файла
-
origSize - оригинальный размер файла в байтах
-
origWidth - оригинальная ширина изображения в точках
-
origHeight - оригинальная высота изображения в точках
-
origDate - оригинальная дата создания файла
-
fileHash - хэш на базе финального содержимого. Можно использовать для отлова дубликатов.
-
fileExt - финальное расширение файла в нижнем регистре (для масштабированных изображений это jpg или webp)
-
fileSize - финальный размер файла в байтах (для изображений - после масштабирования)
-
fileWidth - финальная ширина изображения в точках (после масштабирования)
-
fileHeight - финальная высота изображения в точках (после масштабирования)
-
fileMime - финальный mime-тип файла (для масштабированных изображений это будет image/jpeg или image/webp)
-
thumb - base64-кодированная превьюшка
-
status - статус (значение одной из констант
STATUS_xxx
). По-умолчанию устанавливается равнымSTATUS_PENDING
. В начале закачки меняется наSTATUS_UPLOADING
и по окончании закачки в зависимости от результата принимает значениеSTATUS_SUCCESS
илиSTATUS_ERROR
. -
progress - прогресс загрузки в процентах
-
error - текст ошибки либо пустая строка
-
filename - имя файла на сервере с расширением (доступно только после загрузки, пустая строка при ошибке)
-
url - URL загруженного файла (доступно только после загрузки если разрешено его получать, пустая строка при ошибке)
-
base64data - содержимое файла в формате base64-строки
-
url - (строка) URL для загрузки
-
headers - (структура) дополнительные заголовки, отправляемые на сервер
-
meta - (структура) дополнительные данные, отправляемые при закачке с каждым файлом в поле meta (для обеспечения безопасности, идентификации и т.д.)
-
finalImageMime - (строка) Тип изображения, которое будет получено после масштабирования и поворота.
Варианты:
- 'original' - не производить масштабирование и поворот, закачивать изображения как обычные файлы
- 'image/jpeg' - конвертировать в JPEG
- 'image/webp' - конвертировать в WEBP
-
maxImageWidth - (целое число) ширина изображения, к которой оно будет масштабировано (0 - не масштабировать, используется только когда
finalImageMime != 'original'
) -
maxImageHeight - (целое число) высота изображения, к которой оно будет масштабировано (0 - не масштабировать, используется только когда
finalImageMime != 'original'
) -
quality - (целое число) качество JPEG или WEBP (используется только когда
finalImageMime != 'original'
) -
maxTasks - (целое число) максимальное количество одновременных закачек
-
thumbWidth - (целое число) ширина превьюшки в точках (0 - превьюшки не нужны, используется только когда
finalImageMime != 'original'
) -
thumbHeight - (целое число) высота превьюшки в точках (0 - превьюшки не нужны, используется только когда
finalImageMime != 'original'
)
Ни один из коллбэков не является обязательным.
Многие из коллбэков получают в качестве параметра объект вспомогательного
класса FileInfo
. Данный объект передается по ссылке, соответсвенно можно
отслеживать изменения данных, не используя обработчики. Так же в некоторых
случаях можно изменять данные в переданном объекте, но нужно четко понимать что
вы делаете, чтобы это не повлияло на работоспособность кода и не привело к
трудноуловимым ошибкам.
-
beforeFileProcessing(FileInfo fInfo) - Вызывается перед началом обработки очередного файла. Получает объект
FileInfo
(на данный момент заполнены только поля orig*).Должен вернуть логическое значение - разрешение на продолжение обработки. -
afterFileProcessing(FileInfo fInfo) - Вызывается после завершения обработки файла. Для каждого файла, получает полностью заполненный объект
FileInfo
. Здесь можно добавить дополнительную проверку на размер файла для картинок, котороые подвергаются масштабированию, т.к. вbeforeFileProcessing()
размер итогового файла еще не известен. Должен вернуть логическое значение - разрешение на добавление в очередь закачки. -
onFileStart(FileInfo fInfo) - Вызывается в момент начала закачки очередного файла (получает объект
FileInfo
файла, закачка которого начата) -
onProgress(FileInfo fInfo) - вызывается при обновлении данных о прогрессе загрузки файла. Значение прогресса находится в
fInfo.progress
. -
onFileUploaded(FileInfo fInfo) - вызывается в момент окончания закачки очередного файла. В этот момент объект
FileInfo
уже содержит ответ сервера. -
onUploadError(FileInfo fInfo) - Вызывается при ошибке закачки. В этот момент объект
FileInfo
уже содержит текст ошибки, которую вернул сервер (в полеerror
). -
onEnd() - в момент окончания всех заданий в очереди
-
async addFiles(files) - Добавляет файлы в очередь. Асинхронный метод.
-
start() - начинает процесс закачки
При загрузке на сервер отправляется объект FileInfo
, дополнительно содержащий
поля:
-
base64data - base64-кодированное содержимое файла
-
meta - дополнительные данные (значение параметра meta)
Следует учесть, что в отправляемом на сервер объекте отсутствуют поля:
-
thumb - base64-кодированная превьюшка
-
status - статус (pending, uploading, success, error)
-
progress - прогресс загрузки в процентах (целое 0 - 100)
-
error - текст ошибки либо пустая строка
-
filename - имя файла на сервере с расширением (доступно только после загрузки, пустая строка при ошибке)
-
url - URL загруженного файла (доступно только после загрузки если разрешено его получать, пустая строка при ошибке)
Сервер после загрузки должен прислать структуру, содержащую следующие поля:
-
status - статус результата. При нормальном окончании это поле должно содержать строку
ok
. Любое другое значение означает ошибку, при этом текст ошибки должен быть помещен в полеerror
-
guid - уникальный идентификатор обрабатываемого файла. Пример: ' a8e9034e-ce4b-4329-a734-80252fcc89d4'
-
filename - имя файла на сервере с расширением (пустая строка при ошибке)
-
url - URL загруженного файла (если разрешено его получать, пустая строка при ошибке)
-
error - текст ошибки или пустая строка
const Uploader = require('moonk-file-uploader');
try {
const uploader = new Uploader({
url: 'https://mysite.com/upload',
// добавляем обработчик для фильтрации неугодных файлов
beforeFileProcessing(fi) {
// например, разрешаем загрузку только JPEG
return fi.origMime == 'image/jpeg';
},
// образотчик окончания загрузки
onEnd() {
alert('Закачка завершена');
},
...
});
// добавляем файлы (список получен из <input type="file" />)
await uploader.addFiles(files);
// стартуем закачку
uploader.start();
}
catch(e) {
alert('Браузер не поддерживает интерфейс чтения файлов.');
}
// где-то внутри обработчика POST-запроса
let imgBase64 = request.body.base64data;
// собираем простое уникальное имя файла
const filename = request.body.guid + '.' + request.body.fileExt;
// пока будем складывать в /tmp
const fullPath = '/tmp/' + filename;
// отрезаем заголовок base64
const dataPos = imgBase64.indexOf(',');
imgBase64 = imgBase64.substr(dataPos + 1);
try {
const buff = new Buffer(imgBase64, 'base64');
const fs = require('fs');
fs.writeFileSync(fullPath, buff);
return {
status: 'ok', // флаг удачного выполнения
guid: request.body.guid,
filename,
url: 'https://mysite.com/download/' + filename,
error: ''
}
}
catch(e) {
return {
status: 'error', // флаг ошибки
guid: request.body.guid,
filename: '',
url: '',
error: e.message
}
}