Коли працюєш з завантаженням файлів у Node.js, Multer часто є стандартним посередником. За замовчуванням Multer пропонує два механізми збереження:
Джерело коду Multer
- DiskStorage: Зберігає файли на локальному диску сервера.
- MemoryStorage: Тимчасово зберігає файли в пам'яті як об'єкти Buffer.
Хоча ці опції є достатніми для багатьох випадків, вони можуть бути не зовсім підходящими для сценаріїв, коли потрібно:
- Зберігати файли безпосередньо в хмарному сховищі (наприклад, AWS S3, Google Cloud Storage тощо).
- Використовувати власну логіку чи робочий процес для обробки файлів, як-от правила іменування чи динамічний вибір сховища.
Тут на допомогу приходять кастомні механізми збереження. Multer дозволяє розробникам визначати власні механізми збереження для задоволення специфічних вимог.
У цій статті ми розглянемо, як створити кастомний механізм збереження Multer для завантаження файлів безпосередньо в AWS S3.
Для демонстрації того, як створити кастомний механізм збереження Multer, ми почнемо з побудови простого API на Node.js. Нижченаведений код встановлює основу для цього API:
Спочатку завантажте необхідні пакети:
npm install express multer aws-sdk uuid
//app.js
const express = require('express');
const app = express();
const port = 3000;
const uploadRoute = require('./routes/upload-files.route');
app.get('/', (req, res) => {
res.json('Hello CustomStorage S3!');
});
app.use('/api', uploadRoute);
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
Щоб реалізувати кастомний механізм збереження для AWS S3, центральною частиною буде основний метод, який обробляє процес завантаження файлів.
У нашій реалізації кастомного збереження, це метод _handleFile
.
Нижче наведена реалізація кастомного механізму збереження.
Щоб налаштувати власний бакет S3, перегляньте:
https://console.cloud.google.com
const AWS = require('aws-sdk');
const { v4: uuidv4 } = require('uuid'); // Для генерування унікальних імен файлів
// Налаштування AWS S3
const s3 = new AWS.S3({
endpoint: 'https://storage.googleapis.com',
credentials: {
accessKeyId: '',
secretAccessKey: ''
}
}); // ЗАУВАЖЕННЯ: Замініть ці облікові дані на змінні середовища у виробничому середовищі!
// Кастомний механізм збереження
class S3StorageEngine {
constructor(bucketName) {
this.bucketName = bucketName; // Назва бакету, куди будуть завантажуватися файли
}
// Основний метод для обробки завантаження файлів
_handleFile(req, file, cb) {
console.log('Завантаження файлу', file.stream);
// Генерація унікального ключа для файлу
const key = `${uuidv4()}-${file.originalname}`;
// Визначення параметрів для завантаження в S3
const uploadParams = {
Bucket: this.bucketName,
Key: key,
Body: file.stream,
ContentType: file.mimetype,
};
// Завантаження файлу в S3
s3.upload(uploadParams, (err, data) => {
if (err) {
console.log('Помилка під час завантаження файлу', err);
return cb(err); // Виклик зворотного зв'язку з помилкою
}
// Виклик зворотного зв'язку з метаданими файлу
cb(null, {
key: data.Key,
location: data.Location,
});
});
}
// Опційний метод для видалення файлів
_removeFile(req, file, cb) {
const deleteParams = {
Bucket: this.bucketName,
Key: file.key,
};
s3.deleteObject(deleteParams, (err) => {
if (err) {
return cb(err); // Виклик зворотного зв'язку з помилкою
}
cb(null); // Виклик зворотного зв'язку успішно
});
}
}
module.exports = S3StorageEngine;
Тепер, коли ми створили кастомний механізм збереження для S3, давайте подивимося, як використовувати його в API для обробки завантажень та видалень файлів.
Ось реалізація:
const express = require('express');
const S3StorageEngine = require('../storage/multer-s3-custom-storage');
const multer = require('multer');
const customStorage = new S3StorageEngine('sayman-bucket'); // Замініть 'sayman-bucket' на вашу фактичну назву бакету
const router = express.Router();
const upload = multer({ storage: customStorage });
// Маршрут для обробки завантаження файлів
router.post('/upload', upload.single('file'), (req, res) => {
res.json({
file: req.file, // Повертає метадані завантаженого файлу
});
});
// Маршрут для обробки видалення файлів
router.delete('/delete/:key', (req, res) => {
const file = {
key: req.params?.key, // Ключ файлу для видалення з S3
};
// Використовуємо метод _removeFile кастомного механізму збереження для видалення файлу
customStorage._removeFile(req, file, (err) => {
if (err) {
return res.status(500).json({
message: 'Помилка під час видалення файлу',
error: err.message,
});
}
res.json({ message: 'Файл успішно видалено' });
});
});
module.exports = router;
З цією реалізацією ви тепер маєте повністю функціональне API для завантаження та керування файлами в AWS S3 за допомогою кастомного механізму збереження Multer!
У цій статті ми показали, як створити кастомний механізм збереження Multer для завантаження файлів безпосередньо в AWS S3.
Хоча це покриває основи використання Multer для кастомного збереження, розуміння того, як Multer обробляє файли "під капотом" є ключем до розкриття його повного потенціалу.
У наступній статті я поглиблюсь у:
- Як Multer перехоплює потоки файлів.
Перекладено з: Building Custom Multer Storage for S3 File Uploads with Node.js