feat: assets controller & serve course image

This commit is contained in:
Sergey Yarkov 2021-10-20 23:45:36 +03:00
parent 30fdfa08b6
commit ee25d495e1
9 changed files with 137 additions and 5 deletions

View File

@ -0,0 +1,39 @@
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { Exception, inject, Ioc } from '@adonisjs/core/build/standalone';
/**
* Services
*/
import AssetsService from 'App/Services/AssetsService';
import BaseController from '../BaseController';
@inject()
export default class AssetsController extends BaseController {
private assetsService: AssetsService;
constructor(assetsService: AssetsService) {
super();
this.assetsService = assetsService;
}
/**
* Send background image of course
* GET /media/images/courses/:fileName
*/
public async serveCourseImage(ctx: HttpContextContract) {
const result = await this.assetsService.getCourseImagePath(ctx.params.fileName);
if (typeof result !== 'string') {
if (!result.success && result.error) {
throw new Exception(result.message, result.status, result.error.code);
}
return this.sendResponse(ctx, result.data, result.message, result.status);
}
return this.sendFile(ctx, result);
}
}
new Ioc().make(AssetsController);

View File

@ -12,4 +12,8 @@ export default class BaseController {
return ctx.response.status(response.status).send(response); return ctx.response.status(response.status).send(response);
} }
public sendFile(ctx: HttpContextContract, path: string) {
return ctx.response.download(path);
}
} }

View File

@ -5,7 +5,7 @@ export default class Image extends BaseModel {
@column({ isPrimary: true }) @column({ isPrimary: true })
public id: number; public id: number;
@column() @column({ serializeAs: null })
public path: string; public path: string;
@column() @column()

View File

@ -209,9 +209,11 @@ export default class CourseRepository {
*/ */
public async delete(id: string | number): Promise<Course | null> { public async delete(id: string | number): Promise<Course | null> {
const course = await this.Course.query() const course = await this.Course.query()
.preload('teacher')
.preload('category') .preload('category')
.preload('lessons') .preload('image')
.withCount('students')
.withCount('likes')
.withCount('lessons')
.where('id', id) .where('id', id)
.first(); .first();

View File

@ -15,14 +15,26 @@ export default class ImageRepository {
return image; return image;
} }
public async getByFileName(name: string): Promise<Image | null> {
const image = await this.Image.query().where('name', name).first();
return image;
}
public async getAll(): Promise<Image[]> { public async getAll(): Promise<Image[]> {
const images = await this.Image.query(); const images = await this.Image.query();
return images; return images;
} }
public async create(file: MultipartFileContract): Promise<Image> { public async create(file: MultipartFileContract): Promise<Image> {
await file.moveToDisk('./images'); /**
const image = await this.Image.create({ name: file.clientName, path: file.filePath, ext: file.extname }); * Save image to disk
*/
await file.moveToDisk('images/courses');
/**
* Save image to database
*/
const image = await this.Image.create({ name: file.fileName, path: file.filePath, ext: file.extname });
return image; return image;
} }
@ -30,7 +42,14 @@ export default class ImageRepository {
const image = await this.Image.query().where('id', id).first(); const image = await this.Image.query().where('id', id).first();
if (image) { if (image) {
/**
* Delete from drive
*/
await Drive.delete(image.path); await Drive.delete(image.path);
/**
* Delete from database
*/
await image.delete(); await image.delete();
return image; return image;
} }

View File

@ -0,0 +1,47 @@
import { inject, Ioc } from '@adonisjs/core/build/standalone';
import Application from '@ioc:Adonis/Core/Application';
/**
* Datatypes
*/
import IResponse from 'App/Datatypes/Interfaces/IResponse';
import HttpStatusEnum from 'App/Datatypes/Enums/HttpStatusEnum';
/**
* Reposirories
*/
import ImageRepository from 'App/Repositories/ImageRepository';
@inject()
export default class AssetsService {
private imageRepository: ImageRepository;
constructor(imageRepository: ImageRepository) {
this.imageRepository = imageRepository;
}
/**
*
* @param name Image name
* @returns Pathname
*/
public async getCourseImagePath(name: string): Promise<IResponse | string> {
const image = await this.imageRepository.getByFileName(name);
if (!image) {
return {
success: false,
status: HttpStatusEnum.NOT_FOUND,
message: 'Image not found.',
data: {},
error: {
code: 'E_NOT_FOUND',
},
};
}
return Application.tmpPath(`uploads/images/courses/${image.name}`);
}
}
new Ioc().make(AssetsService);

View File

@ -2,7 +2,15 @@
import Route from '@ioc:Adonis/Core/Route'; import Route from '@ioc:Adonis/Core/Route';
Route.group(() => { Route.group(() => {
/**
* v1
*/
require('./apis/v1/index'); require('./apis/v1/index');
/**
* Assets routes
*/
require('./apis/assets/index');
}) })
.prefix('api') .prefix('api')
.as('api'); .as('api');

View File

@ -0,0 +1,10 @@
import Route from '@ioc:Adonis/Core/Route';
Route.group(() => {
/**
* Serve background image for course
*/
Route.get('/images/courses/:fileName', 'Api/AssetsController.serveCourseImage').as('serve.course.image');
})
.prefix('assets')
.as('assets');

View File

@ -22,5 +22,8 @@ import Route from '@ioc:Adonis/Core/Route';
*/ */
Route.group(() => { Route.group(() => {
/**
* Api routes
*/
require('./api'); require('./api');
}); });