File uploads

Основные подходы к загрузке файлов

В SvelteKit загрузка файлов может реализовываться через два основных подхода: классическая форма HTML с multipart/form-data и асинхронная загрузка через Fetch API. Каждый подход имеет свои преимущества:

  • Форма HTML (<form enctype="multipart/form-data">) подходит для простых случаев, когда требуется отправить файл вместе с другими данными формы. SvelteKit автоматически обрабатывает формы через actions.
  • Fetch API позволяет реализовать более гибкую работу с файлами, включая прогресс-бар, предварительный просмотр и контроль ошибок на уровне фронтенда.

Настройка формы для загрузки файлов

Простейший пример формы в SvelteKit с использованием multipart/form-data выглядит так:

<form method="POST" enctype="multipart/form-data" use:enhance>
  <input type="file" name="avatar" />
  <button type="submit">Загрузить</button>
</form>
  • Атрибут enctype="multipart/form-data" обязателен для передачи файлов.
  • use:enhance — это SvelteKit action enhancer, который позволяет выполнять отправку асинхронно и получать результат без перезагрузки страницы.

Обработка загрузки на сервере

На серверной стороне SvelteKit файлы можно обрабатывать через actions или endpoints:

// src/routes/upload/+server.js
import { json } from '@sveltejs/kit';
import fs from 'fs';
import path from 'path';

export const POST = async ({ request }) => {
  const data = await request.formData();
  const file = data.get('avatar');

  if (!file) return json({ error: 'Файл не найден' }, { status: 400 });

  const buffer = Buffer.from(await file.arrayBuffer());
  const filePath = path.join('uploads', file.name);

  fs.writeFileSync(filePath, buffer);

  return json({ message: 'Файл успешно загружен', filename: file.name });
};

Ключевые моменты:

  • Используется request.formData() для извлечения файлов.
  • file.arrayBuffer() преобразует содержимое файла в буфер для сохранения.
  • Хранение файлов должно быть безопасным — обычно применяют отдельную папку и проверку имени файла.

Асинхронная загрузка через Fetch API

Для улучшенного UX можно загружать файлы через Jav * aScript:

<script>
  let file;

  async function uploadFile() {
    if (!file) return;

    const formData = new FormData();
    formData.append('avatar', file);

    const res = await fetch('/upload', {
      method: 'POST',
      body: formData
    });

    const result = await res.json();
    console.log(result);
  }
</script>

<input type="file" on:change={(e) => (file = e.target.files[0])} />
<button on:click={uploadFile}>Загрузить</button>
  • Позволяет реализовать прогресс-бар, предварительный просмотр, проверку типа и размера файла до отправки.
  • Возможна интеграция с UI-библиотеками для SvelteKit, например Svelte Material UI или Flowbite Svelte, для отображения состояния загрузки.

Обработка нескольких файлов

Чтобы разрешить загрузку нескольких файлов:

<input type="file" multiple on:change={(e) => (files = Array.from(e.target.files))} />

На серверной стороне:

for (const file of data.getAll('avatars')) {
  const buffer = Buffer.from(await file.arrayBuffer());
  fs.writeFileSync(path.join('uploads', file.name), buffer);
}
  • Использование data.getAll('avatars') позволяет обрабатывать массив файлов.
  • UI-библиотеки предоставляют удобные компоненты для множественного выбора и отображения списка файлов.

Прогресс загрузки и UX

Для отображения прогресса загрузки в SvelteKit используют XMLHttpRequest или Fetch API с ReadableStream:

const xhr = new XMLHttpRequest();
xhr.upload.onprogr ess = (e) => {
  if (e.lengthComputable) {
    progress = (e.loaded / e.total) * 100;
  }
};
xhr.open('POST', '/upload');
xhr.send(formData);

Особенности:

  • Позволяет показывать процент загрузки.
  • Можно интегрировать с анимацией из UI-библиотек для красивого интерфейса.

Проверка типа и размера файлов

Для предотвращения ошибок и атак полезно проверять тип и размер:

function validateFile(file) {
  const allowedTypes = ['image/png', 'image/jpeg'];
  const maxSize = 5 * 1024 * 1024; // 5MB
  return allowedTypes.includes(file.type) && file.size <= maxSize;
}
  • В UI можно отображать уведомления об ошибках через готовые компоненты.
  • Серверная проверка обязательна, фронтенд проверка лишь улучшает UX.

Интеграция с SvelteKit UI библиотеками

Популярные UI-библиотеки предлагают готовые элементы для файлов:

  • Svelte Material UISMUI TextField и SMUI Button позволяют легко стилизовать поля и кнопки загрузки.
  • Flowbite Svelte – компоненты FileInput с поддержкой multiple и drag-and-drop.
  • Carbon Components Svelte – предоставляет FileUploader с прогрессом и drag-and-drop интерфейсом.

Использование библиотек упрощает:

  • Отображение ошибок.
  • Анимацию загрузки.
  • Предварительный просмотр изображений и файлов.
  • Множественный выбор и drag-and-drop.

Drag-and-Drop поддержка

Для drag-and-drop реализуют событие drop и предотвращают стандартное поведение браузера:

<div on:dragover|preventDefault on:drop|preventDefault={(e) => handleDrop(e)}>
  Перетащите файлы сюда
</div>

<script>
function handleDrop(event) {
  files = Array.from(event.dataTransfer.files);
}
</script>
  • Можно сочетать с компонентами UI-библиотек для визуального эффекта.
  • Позволяет делать интерфейс более интуитивным для пользователя.

Резюме по best practices

  • Всегда использовать multipart/form-data для отправки файлов.
  • Проверять тип и размер файлов на клиенте и сервере.
  • Использовать асинхронную загрузку для улучшения UX.
  • Интегрировать с UI-библиотеками для красивого интерфейса и прогресс-баров.
  • Реализовывать drag-and-drop и множественный выбор через соответствующие события.

Загрузка файлов в SvelteKit сочетает простоту форм с возможностью сложного асинхронного управления через Fetch API и готовые компоненты UI-библиотек. Это позволяет создавать гибкие и отзывчивые интерфейсы, обеспечивая при этом безопасность и контроль над файлами.