Перейти к основному содержимому

Хранилище

SDK предоставляет методы для загрузки файлов в хранилище EMD Cloud с поддержкой TUS протокола для надежной загрузки больших файлов.

Установка зависимостей

Для работы с хранилищем требуются peer dependencies:

npm install tus-js-client uuid

Загрузка файлов

upload()

Загружает файл в хранилище с использованием TUS протокола.

Синтаксис

await emdCloud.uploader.upload(file, options);

Параметры

ПараметрТипОписание
fileFile|BlobФайл для загрузки
onProgressfunctionCallback для отслеживания прогресса
onSuccessfunctionCallback при успешной загрузке
onErrorfunctionCallback при ошибке
metadataobjectДополнительные метаданные файла

Примеры

Простая загрузка:

const file = document.querySelector('input[type="file"]').files[0];

try {
const result = await emdCloud.uploader.upload(file, {
onProgress: (bytesUploaded, bytesTotal) => {
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
console.log(`Загружено: ${percentage}%`);
},
onSuccess: () => {
console.log('Файл успешно загружен!');
},
onError: (error) => {
console.error('Ошибка загрузки:', error);
}
});

console.log('ID файла:', result.fileId);
console.log('URL файла:', result.url);

} catch (error) {
console.error('Ошибка:', error);
}

Загрузка с метаданными:

const result = await emdCloud.uploader.upload(file, {
metadata: {
filename: 'document.pdf',
filetype: 'application/pdf',
category: 'documents',
userId: 'user-123'
},
onProgress: (uploaded, total) => {
updateProgressBar(uploaded, total);
}
});

Загрузка изображения:

async function uploadImage(imageFile) {
const result = await emdCloud.uploader.upload(imageFile, {
metadata: {
filename: imageFile.name,
filetype: imageFile.type
},
onProgress: (uploaded, total) => {
const percent = Math.round((uploaded / total) * 100);
document.getElementById('progress').textContent = `${percent}%`;
},
onSuccess: () => {
console.log('Изображение загружено');
}
});

// Используем URL для отображения
const img = document.createElement('img');
img.src = result.url;
document.body.appendChild(img);

return result;
}

Компонент загрузки с прогресс-баром

class FileUploader {
constructor(emdCloud) {
this.emdCloud = emdCloud;
this.uploads = new Map();
}

async uploadFile(file, uploadId = null) {
const id = uploadId || this.generateId();

this.uploads.set(id, {
file: file,
progress: 0,
status: 'uploading'
});

try {
const result = await this.emdCloud.uploader.upload(file, {
onProgress: (uploaded, total) => {
const progress = Math.round((uploaded / total) * 100);
this.updateProgress(id, progress);
},
onSuccess: () => {
this.updateStatus(id, 'completed');
},
onError: (error) => {
this.updateStatus(id, 'error');
console.error('Ошибка загрузки:', error);
}
});

this.uploads.get(id).result = result;
return result;

} catch (error) {
this.updateStatus(id, 'error');
throw error;
}
}

updateProgress(id, progress) {
const upload = this.uploads.get(id);
if (upload) {
upload.progress = progress;
this.onProgressUpdate?.(id, progress);
}
}

updateStatus(id, status) {
const upload = this.uploads.get(id);
if (upload) {
upload.status = status;
this.onStatusUpdate?.(id, status);
}
}

generateId() {
return `upload-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}

getUpload(id) {
return this.uploads.get(id);
}

getAllUploads() {
return Array.from(this.uploads.values());
}
}

// Использование
const uploader = new FileUploader(emdCloud);

uploader.onProgressUpdate = (id, progress) => {
console.log(`Upload ${id}: ${progress}%`);
updateUIProgress(id, progress);
};

uploader.onStatusUpdate = (id, status) => {
console.log(`Upload ${id}: ${status}`);
updateUIStatus(id, status);
};

// Загрузить файл
const result = await uploader.uploadFile(file);

Множественная загрузка

async function uploadMultipleFiles(files) {
const uploads = Array.from(files).map(file => {
return emdCloud.uploader.upload(file, {
metadata: {
filename: file.name,
filetype: file.type
},
onProgress: (uploaded, total) => {
console.log(`${file.name}: ${Math.round((uploaded/total)*100)}%`);
}
});
});

try {
const results = await Promise.all(uploads);
console.log('Все файлы загружены:', results);
return results;
} catch (error) {
console.error('Ошибка при загрузке файлов:', error);
throw error;
}
}

// Использование
const fileInput = document.querySelector('input[type="file"][multiple]');
const results = await uploadMultipleFiles(fileInput.files);

Загрузка с предпросмотром

async function uploadImageWithPreview(file) {
// Создаем предпросмотр
const reader = new FileReader();
reader.onload = (e) => {
const preview = document.getElementById('preview');
preview.src = e.target.result;
};
reader.readAsDataURL(file);

// Загружаем файл
const result = await emdCloud.uploader.upload(file, {
metadata: {
filename: file.name,
filetype: file.type
},
onProgress: (uploaded, total) => {
const percent = Math.round((uploaded / total) * 100);
document.getElementById('upload-progress').value = percent;
},
onSuccess: () => {
console.log('Загрузка завершена');
// Заменяем предпросмотр на реальный URL
document.getElementById('preview').src = result.url;
}
});

return result;
}

Обработка ошибок

async function uploadWithErrorHandling(file) {
try {
const result = await emdCloud.uploader.upload(file, {
onProgress: (uploaded, total) => {
updateProgress(uploaded, total);
},
onError: (error) => {
// Обработка ошибок во время загрузки
if (error.message.includes('network')) {
showError('Проблема с сетью. Проверьте подключение.');
} else if (error.message.includes('size')) {
showError('Файл слишком большой.');
} else {
showError('Ошибка загрузки файла.');
}
}
});

return result;

} catch (error) {
// Обработка критических ошибок
console.error('Критическая ошибка:', error);

if (error.status === 401) {
showError('Необходима авторизация');
redirectToLogin();
} else if (error.status === 413) {
showError('Файл слишком большой');
} else if (error.status === 415) {
showError('Неподдерживаемый тип файла');
} else {
showError('Не удалось загрузить файл');
}

throw error;
}
}

Валидация файлов

function validateFile(file, options = {}) {
const {
maxSize = 10 * 1024 * 1024, // 10 MB
allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf']
} = options;

// Проверка размера
if (file.size > maxSize) {
throw new Error(`Файл слишком большой. Максимум: ${maxSize / 1024 / 1024} MB`);
}

// Проверка типа
if (!allowedTypes.includes(file.type)) {
throw new Error(`Неподдерживаемый тип файла: ${file.type}`);
}

return true;
}

async function uploadWithValidation(file) {
try {
// Валидация перед загрузкой
validateFile(file, {
maxSize: 5 * 1024 * 1024, // 5 MB
allowedTypes: ['image/jpeg', 'image/png']
});

// Загрузка
const result = await emdCloud.uploader.upload(file);
return result;

} catch (error) {
console.error('Ошибка:', error.message);
showError(error.message);
}
}

Интеграция с формами

// HTML
// <form id="upload-form">
// <input type="file" id="file-input" accept="image/*" required>
// <progress id="progress" value="0" max="100"></progress>
// <button type="submit">Загрузить</button>
// </form>

document.getElementById('upload-form').addEventListener('submit', async (e) => {
e.preventDefault();

const fileInput = document.getElementById('file-input');
const progressBar = document.getElementById('progress');
const file = fileInput.files[0];

if (!file) {
alert('Выберите файл');
return;
}

try {
const result = await emdCloud.uploader.upload(file, {
onProgress: (uploaded, total) => {
const percent = (uploaded / total) * 100;
progressBar.value = percent;
},
onSuccess: () => {
alert('Файл успешно загружен!');
fileInput.value = ''; // Очистить input
progressBar.value = 0;
}
});

console.log('Файл загружен:', result.url);

} catch (error) {
alert('Ошибка загрузки: ' + error.message);
}
});

Best Practices

Показывайте прогресс

// ✅ Хорошо: информируем пользователя о прогрессе
await emdCloud.uploader.upload(file, {
onProgress: (uploaded, total) => {
const percent = Math.round((uploaded / total) * 100);
updateProgressBar(percent);
updateStatusText(`Загружено ${percent}%`);
}
});

Валидируйте файлы

// ✅ Хорошо: проверяем файл перед загрузкой
if (file.size > MAX_FILE_SIZE) {
showError('Файл слишком большой');
return;
}

if (!ALLOWED_TYPES.includes(file.type)) {
showError('Неподдерживаемый тип файла');
return;
}

Обрабатывайте ошибки

// ✅ Хорошо: обрабатываем ошибки и информируем пользователя
try {
await emdCloud.uploader.upload(file, {
onError: (error) => {
showErrorNotification(error.message);
}
});
} catch (error) {
showRetryButton();
}

Следующие шаги

Полезные ссылки