1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-08-03 12:35:23 +02:00

S3 uploads support (#273)

* finish s3 uploads implementation

* remove unnecessary file

* fix docs

* update DEVELOPMENT.md

* update doc

* update default uploads path
This commit is contained in:
Nikita Melnikov 2022-10-08 14:26:11 +04:00 committed by GitHub
parent 55b4b3ee61
commit 8c794304b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 1373 additions and 248 deletions

View file

@ -1,31 +1,13 @@
import { Request, Response, Router } from 'express';
import multer, { StorageEngine } from 'multer';
import mime from 'mime';
import mkdirp from 'mkdirp';
import multer from 'multer';
import Transport from '../../controllers/transport.js';
import { random16 } from '../../utils/crypto.js';
import appConfig from '../../utils/appConfig.js';
import { FileData } from '../../models/file.js';
import { uploadsDriver } from '../../uploads/index.js';
const router = Router();
/**
* Multer storage for uploaded files and images
*
* @type {StorageEngine}
*/
const storage: StorageEngine = multer.diskStorage({
destination: (req, file, cb) => {
const dir: string = appConfig.uploads || 'public/uploads';
mkdirp(dir);
cb(null, dir);
},
filename: async (req, file, cb) => {
const filename = await random16();
cb(null, `${filename}.${mime.getExtension(file.mimetype)}`);
},
});
const storage = uploadsDriver.createStorageEngine();
/**
* Multer middleware for image uploading
@ -50,50 +32,66 @@ const imageUploader = multer({
* Multer middleware for file uploading
*/
const fileUploader = multer({
storage: storage,
storage,
}).fields([ {
name: 'file',
maxCount: 1,
} ]);
/**
* Computes URL to uploaded file
*
* @param fileData - file data to process
*/
function getFileUrl(fileData: FileData): string {
if (appConfig.uploads.driver === 'local') {
return '/uploads/' + fileData.filename;
} else {
const baseUrlWithoutTrailingSlash = appConfig.uploads.s3.baseUrl.replace(/\/+$/, '');
return baseUrlWithoutTrailingSlash + '/' + fileData.filename;
}
}
/**
* Accepts images to upload
*/
router.post('/transport/image', imageUploader, async (req: Request, res: Response) => {
const response = {
success: 0,
message: '',
};
if (req.files === undefined) {
response.message = 'No files found';
res.status(400).json(response);
res.status(400).json({
success: 0,
message: 'No files found',
});
return;
}
if (!('image' in req.files)) {
res.status(400).json(response);
res.status(400).json({
success: 0,
message: 'No images found',
});
return;
}
const fileData = {
...req.files.image[0],
url: '/uploads/' + req.files.image[0].filename,
};
console.log(fileData);
try {
Object.assign(
response,
await Transport.save(fileData, req.body.map ? JSON.parse(req.body.map) : undefined)
);
const fileData = await Transport.save(req.files.image[0]);
const url = getFileUrl(fileData);
response.success = 1;
res.status(200).json(response);
res.status(200).json({
success: 1,
file: {
url,
mime: fileData.mimetype,
size: fileData.size,
},
message: '',
});
} catch (e) {
res.status(500).json(response);
res.status(500).json({
success: 0,
message: e,
});
}
});
@ -101,29 +99,41 @@ router.post('/transport/image', imageUploader, async (req: Request, res: Respons
* Accepts files to upload
*/
router.post('/transport/file', fileUploader, async (req: Request, res: Response) => {
const response = { success: 0 };
if (req.files === undefined) {
res.status(400).json(response);
res.status(400).json({
success: 0,
message: 'No files found',
});
return;
}
if (!('file' in req.files)) {
res.status(400).json(response);
res.status(400).json({
success: 0,
message: 'No file found',
});
return;
}
try {
Object.assign(
response,
await Transport.save(req.files.file[0], req.body.map ? JSON.parse(req.body.map) : undefined)
);
const fileData = await Transport.save(req.files.file[0]);
const url = getFileUrl(fileData);
response.success = 1;
res.status(200).json(response);
res.status(200).json({
success: 1,
file: {
url,
mime: fileData.mimetype,
size: fileData.size,
},
message: '',
});
} catch (e) {
res.status(500).json(response);
res.status(500).json({
success: 0,
message: e,
});
}
});
@ -131,22 +141,34 @@ router.post('/transport/file', fileUploader, async (req: Request, res: Response)
* Accept file url to fetch
*/
router.post('/transport/fetch', multer().none(), async (req: Request, res: Response) => {
const response = { success: 0 };
if (!req.body.url) {
res.status(400).json(response);
res.status(400).json({
success: 0,
message: 'No url provided',
});
return;
}
try {
Object.assign(response, await Transport.fetch(req.body.url, req.body.map ? JSON.parse(req.body.map) : undefined));
const fileData = await Transport.fetch(req.body.url);
const url = getFileUrl(fileData);
response.success = 1;
res.status(200).json(response);
res.status(200).json({
success: 1,
file: {
url,
mime: fileData.mimetype,
size: fileData.size,
},
message: '',
});
} catch (e) {
console.log(e);
res.status(500).json(response);
res.status(500).json({
success: 0,
message: e,
});
}
});