Хранилище
SDK предоставляет методы для загрузки файлов в хранилище EMD Cloud с поддержкой TUS протокола для надежной загрузки больших файлов.
Установка зависимостей
Для работы с хранилищем требуются peer dependencies:
npm install tus-js-client uuid
Загрузка файлов
upload()
Загружает файл в хранилище с использованием TUS протокола.
Синтаксис
await emdCloud.uploader.upload(file, options);
Параметры
| Параметр | Тип | Описание |
|---|---|---|
file | File|Blob | Файл для загрузки |
onProgress | function | Callback для отслеживания прогресса |
onSuccess | function | Callback при успешной загрузке |
onError | function | Callback при ошибке |
metadata | object | Дополнительные метаданные файла |
Примеры
Простая загрузка:
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();
}
Следующие шаги
- 💬 Используйте загрузку для вложений в чатах
- ⚛️ Изучите React хуки для загрузки
- 💡 Посмотрите примеры загрузки файлов