mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-04-08 21:00:58 +00:00
Add MediaService
This service is responsible for operations regarding uploaded media. It should perform save, get and delete operations with the configured backend. The service also checks, if the mime type of the uploaded media is allowed. Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
parent
23ba2026cc
commit
c0cbcc863a
5 changed files with 109 additions and 1 deletions
|
@ -30,6 +30,7 @@
|
|||
"class-transformer": "^0.2.3",
|
||||
"class-validator": "^0.12.2",
|
||||
"connect-typeorm": "^1.1.4",
|
||||
"file-type": "^15.0.1",
|
||||
"raw-body": "^2.4.1",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"rimraf": "^3.0.2",
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { MediaUpload } from './media-upload.entity';
|
||||
import { MediaService } from './media.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([MediaUpload])],
|
||||
imports: [TypeOrmModule.forFeature([MediaUpload]), NotesModule, UsersModule],
|
||||
providers: [MediaService],
|
||||
exports: [MediaService],
|
||||
})
|
||||
export class MediaModule {}
|
||||
|
|
18
src/media/media.service.spec.ts
Normal file
18
src/media/media.service.spec.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { MediaService } from './media.service';
|
||||
|
||||
describe('MediaService', () => {
|
||||
let service: MediaService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [MediaService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<MediaService>(MediaService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
52
src/media/media.service.ts
Normal file
52
src/media/media.service.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import * as FileType from 'file-type';
|
||||
import { Repository } from 'typeorm';
|
||||
import { NotesService } from '../notes/notes.service';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { BackendType } from './backends/backend-type.enum';
|
||||
import { FilesystemBackend } from './backends/filesystem-backend';
|
||||
import { MediaUpload } from './media-upload.entity';
|
||||
import { MulterFile } from './multer-file.interface';
|
||||
|
||||
@Injectable()
|
||||
export class MediaService {
|
||||
constructor(
|
||||
@InjectRepository(MediaUpload)
|
||||
private mediaUploadRepository: Repository<MediaUpload>,
|
||||
private notesService: NotesService,
|
||||
private usersService: UsersService,
|
||||
) {}
|
||||
|
||||
public async saveFile(file: MulterFile, username: string, noteId: string) {
|
||||
const note = await this.notesService.getNoteByIdOrAlias(noteId);
|
||||
const user = await this.usersService.getUserByUsername(username);
|
||||
const fileTypeResult = await FileType.fromBuffer(file.buffer);
|
||||
if (!fileTypeResult) {
|
||||
throw new Error('Could not detect file type.');
|
||||
}
|
||||
if (!MediaService.isAllowedMimeType(fileTypeResult.mime)) {
|
||||
throw new Error('MIME type not allowed');
|
||||
}
|
||||
//TODO: Choose backend according to config
|
||||
const mediaUpload = MediaUpload.create(
|
||||
note,
|
||||
user,
|
||||
fileTypeResult.ext,
|
||||
BackendType.FILEYSTEM,
|
||||
);
|
||||
const backend = new FilesystemBackend();
|
||||
const [url, backendData] = await backend.saveFile(
|
||||
file.buffer,
|
||||
mediaUpload.id,
|
||||
);
|
||||
mediaUpload.backendData = backendData;
|
||||
await this.mediaUploadRepository.save(mediaUpload);
|
||||
return url;
|
||||
}
|
||||
|
||||
private static isAllowedMimeType(mimeType: string): boolean {
|
||||
//TODO: Which mimetypes are allowed?
|
||||
return true;
|
||||
}
|
||||
}
|
32
src/media/multer-file.interface.ts
Normal file
32
src/media/multer-file.interface.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { Readable } from 'stream';
|
||||
|
||||
// Type from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/multer/index.d.ts
|
||||
export interface MulterFile {
|
||||
/** Name of the form field associated with this file. */
|
||||
fieldname: string;
|
||||
/** Name of the file on the uploader's computer. */
|
||||
originalname: string;
|
||||
/**
|
||||
* Value of the `Content-Transfer-Encoding` header for this file.
|
||||
* @deprecated since July 2015
|
||||
* @see RFC 7578, Section 4.7
|
||||
*/
|
||||
encoding: string;
|
||||
/** Value of the `Content-Type` header for this file. */
|
||||
mimetype: string;
|
||||
/** Size of the file in bytes. */
|
||||
size: number;
|
||||
/**
|
||||
* A readable stream of this file. Only available to the `_handleFile`
|
||||
* callback for custom `StorageEngine`s.
|
||||
*/
|
||||
stream: Readable;
|
||||
/** `DiskStorage` only: Directory to which this file has been uploaded. */
|
||||
destination: string;
|
||||
/** `DiskStorage` only: Name of this file within `destination`. */
|
||||
filename: string;
|
||||
/** `DiskStorage` only: Full path to the uploaded file. */
|
||||
path: string;
|
||||
/** `MemoryStorage` only: A Buffer containing the entire file. */
|
||||
buffer: Buffer;
|
||||
}
|
Loading…
Add table
Reference in a new issue