Add "FTP"
64
FTP.md
Normal file
64
FTP.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# FTP/SFTP Галерея
|
||||||
|
|
||||||
|
## Настройка
|
||||||
|
|
||||||
|
В settings.json → `ftpConfig`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"protocol": "sftp", // "ftp" или "sftp"
|
||||||
|
"host": "212.113.122.5",
|
||||||
|
"port": 22, // 21 для FTP, 22 для SFTP
|
||||||
|
"user": "reaspekt",
|
||||||
|
"password": "...", // маскируется в API-ответе
|
||||||
|
"remotePath": "public/newsletter_2026",
|
||||||
|
"baseUrl": "https://email-files.vipavenue.ru/newsletter_2026"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Библиотеки: `basic-ftp` (FTP), `ssh2-sftp-client` (SFTP).
|
||||||
|
|
||||||
|
## Загрузка картинок
|
||||||
|
|
||||||
|
### Из конструктора (drag-and-drop)
|
||||||
|
1. Перетаскиваешь картинку на поле `src` блока
|
||||||
|
2. `handleImageDrop()` → если FTP настроен и у письма есть дата → загружает на FTP
|
||||||
|
3. Иначе → загружает локально (`/api/upload-image`)
|
||||||
|
4. URL подставляется в поле блока
|
||||||
|
|
||||||
|
### Из галереи (модал)
|
||||||
|
1. Кнопка FTP-галереи на поле картинки
|
||||||
|
2. Открывается модал с миниатюрами из папки `{remotePath}/{дата-письма}/`
|
||||||
|
3. Можно выбрать существующую картинку или загрузить новую
|
||||||
|
|
||||||
|
### Пакетная загрузка
|
||||||
|
- `<input type="file" multiple>` — выбор нескольких файлов
|
||||||
|
- Загрузка последовательная (`for...of` с await), не параллельная
|
||||||
|
- `event.target.value = ''` после загрузки — для повторного выбора тех же файлов
|
||||||
|
- Прогресс: `ftpUploadProgress` / `ftpUploadPercent`
|
||||||
|
|
||||||
|
## Безопасность FTP
|
||||||
|
|
||||||
|
- **Path traversal**: `folder` проверяется на `..` и абсолютные пути
|
||||||
|
- **Имя файла**: `fileName.replace(/[^a-zA-Z0-9а-яА-ЯёЁ_-]/g, '_')`
|
||||||
|
- **Макс размер**: 20 МБ (base64 в body)
|
||||||
|
- **Типы файлов**: png, jpg, gif, webp
|
||||||
|
|
||||||
|
## Автонумерация картинок
|
||||||
|
|
||||||
|
Функция `applyAutoImageNumbers()`:
|
||||||
|
1. Берёт `imageBaseUrl` и `imageExt` из настроек
|
||||||
|
2. Проходит по всем блокам с пустыми полями `src`
|
||||||
|
3. Присваивает последовательные номера: `{baseUrl}image__01_.png`, `image__02_.png`, ...
|
||||||
|
|
||||||
|
## Кэширование галереи
|
||||||
|
|
||||||
|
`ftpGalleryCache` — Map `{folder: files[]}` в памяти клиента. При загрузке новой картинки — файл добавляется в кэш без повторного запроса к FTP.
|
||||||
|
|
||||||
|
## Модал галереи
|
||||||
|
|
||||||
|
- Размер: `max-width: 1100px`
|
||||||
|
- Сетка миниатюр: `max-height: 55vh`, миниатюры `height: 100px`
|
||||||
|
- Клик на миниатюру → копирует URL в поле блока
|
||||||
|
- Кнопка удаления на каждой миниатюре (с подтверждением)
|
||||||
|
- Кнопка "Обновить" для перезагрузки списка
|
||||||
Reference in New Issue
Block a user