Skip to content
Snippets Groups Projects
Commit 5eab22bc authored by Ivan Alglave's avatar Ivan Alglave
Browse files

fix: uploading and downloading pdf now works

parent e6d3b32a
No related branches found
No related tags found
1 merge request!8Pdfback
......@@ -107,4 +107,4 @@ dist
config.json
# file where we store pdf
internship-agreements/
\ No newline at end of file
files/*
......@@ -17,6 +17,7 @@
"class-validator": "^0.13.2",
"fastify": "^4.9.2",
"mongoose": "^6.7.2",
"multer": "^1.4.5-lts.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
......@@ -2661,6 +2662,23 @@
"@nestjs/core": "^9.0.0"
}
},
"node_modules/@nestjs/platform-express/node_modules/multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/@nestjs/schematics": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-9.0.3.tgz",
......@@ -7518,9 +7536,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
"integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
"dependencies": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
......@@ -12039,6 +12057,22 @@
"express": "4.18.2",
"multer": "1.4.4-lts.1",
"tslib": "2.4.1"
},
"dependencies": {
"multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
"concat-stream": "^1.5.2",
"mkdirp": "^0.5.4",
"object-assign": "^4.1.1",
"type-is": "^1.6.4",
"xtend": "^4.0.0"
}
}
}
},
"@nestjs/schematics": {
......@@ -15754,9 +15788,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"multer": {
"version": "1.4.4-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz",
"integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==",
"version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
"integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==",
"requires": {
"append-field": "^1.0.0",
"busboy": "^1.0.0",
......
......@@ -33,6 +33,7 @@
"class-validator": "^0.13.2",
"fastify": "^4.9.2",
"mongoose": "^6.7.2",
"multer": "^1.4.5-lts.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
......
......@@ -4,12 +4,14 @@ import config from './config';
import { PeopleModule } from './people/people.module';
import { GroupsModule } from './groups/groups.module';
import { InternshipsModule } from './internships/internships.module';
import { ResourcesModule } from './resources/resources.module';
@Module({
imports: [
PeopleModule,
GroupsModule,
InternshipsModule,
ResourcesModule,
MongooseModule.forRoot(config.mongodb.uri),
],
})
......
export interface IServerConfig {
url: string;
interface IServerConfig {
uri: string;
port: number;
}
export interface IMongodbConfig {
interface IResources {
root: string;
agreements: string;
}
interface IMongodbConfig {
uri: string;
}
export interface IConfig {
server: IServerConfig;
resources: IResources;
mongodb: IMongodbConfig;
}
{
"server": {
"url": "localhost",
"uri": "localhost",
"port": 3001
},
"resources": {
"internshipAgreements": "internship-agreements"
},
"mongodb": {
"uri": "mongodb://localhost:27017/internship-manager"
}
......
{
"server": {
"url": "localhost",
"uri": "localhost",
"port": 3001
},
"resources": {
"internshipAgreements": "internship-agreements"
},
"mongodb": {
"uri": "mongodb://localhost:27017/internship-manager"
}
......
......@@ -8,6 +8,7 @@ const CONFIG_DEV = 'config.json';
const CONFIG_PROD = 'config.prod.json';
let config: IConfig;
console.log(process.env.NODE_ENV);
// Load config based on env
switch (process.env.NODE_ENV) {
case 'dev':
......@@ -30,5 +31,7 @@ switch (process.env.NODE_ENV) {
exit(-1);
}
console.log(config);
// Export config
export default config;
......@@ -120,6 +120,7 @@ export class InternshipDao {
content: string | boolean,
): Promise<Internship | void> =>
new Promise((resolve, reject) => {
console.log('%s/%s: {%s}', studentId, state, content);
if (!isStateValid(state)) reject(BAD_REQUEST);
console.log(content);
let nextState: string, contentHolder: string;
......
......@@ -16,7 +16,6 @@ import { CreateInternshipDto } from './dto/create-internship.dto';
import { InternshipEntity } from './entities/internship.entity';
import { InternshipService } from './internships.service';
import { FileInterceptor } from '@nestjs/platform-express';
import * as path from 'path';
import {
STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION,
STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION,
......@@ -24,6 +23,7 @@ import {
import config from 'src/config';
import { Optional } from '@nestjs/common/decorators';
import { v4 } from 'uuid';
import { diskStorage } from 'multer';
@Controller('internships')
@UseInterceptors(HttpInterceptor)
......@@ -57,14 +57,16 @@ export class InternshipsController {
return this._internshipsService.update(params.studentId, internshipDto);
}
// uploads even if invalid state...
@Put(':studentId/:state')
@UseInterceptors(
FileInterceptor('pdf', {
dest: './internship-agreements',
fileFilter: (req, file, cb) => {
file.filename = `${v4()}.pdf`;
cb(null, true);
},
storage: diskStorage({
destination: './files',
filename: (_req, _file, cb) => {
return cb(null, `${v4()}.pdf`);
},
}),
}),
)
updateState(
......@@ -74,12 +76,6 @@ export class InternshipsController {
): Promise<InternshipEntity | void> {
if (!InternshipStates.isStateValid(params.state))
throw BAD_TRACKING_STATE(params.state);
// AMINE : Handle PDF file upload -> save file in /pdf/ folder and set content as local file URL. In case of step with no file, set content as true/false
//case where there isn't a file
//Deux premiers états
if (
params.state === STATE_STUDENT_ENTERS_INTERNSHIP_INFORMATION ||
params.state === STATE_RESPONSIBLE_ACCEPTS_INTERNSHIP_INFORMATION
......@@ -92,18 +88,12 @@ export class InternshipsController {
);
}
//case where there is a file
if (!file) throw BAD_REQUEST;
console.log(file);
console.log(config);
console.log(params.state);
return this._internshipsService.updateTracking(
params.studentId,
params.state,
path.join(
`${config.server.url}:${config.server.port}`,
file.path,
file.fieldname,
),
`${config.server.uri}:${config.server.port}/resources/agreements/${file.filename}`,
);
}
......
import config from './config';
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import config from './config';
async function bootstrap() {
const env = process.env.NODE_ENV;
......
import {
Controller,
Get,
Param,
UseInterceptors,
Res,
StreamableFile,
} from '@nestjs/common';
import { NOT_FOUND } from 'src/shared/HttpError';
import { HttpInterceptor } from '../interceptors/http.interceptor';
import { Response } from 'express';
import { createReadStream, existsSync } from 'fs';
@Controller('resources')
@UseInterceptors(HttpInterceptor)
export class ResourcesController {
@Get('agreements/:filename')
serveAgreement(
@Param('filename') filename,
@Res({ passthrough: true }) res: Response,
): StreamableFile {
const filepath = `files\\${filename}`;
if (!existsSync(filepath)) throw NOT_FOUND;
const file = createReadStream(filepath);
res.set({
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename="agreement.pdf"',
});
return new StreamableFile(file);
}
}
import { Module, Logger } from '@nestjs/common';
import { ResourcesController } from './resources.controller';
@Module({
controllers: [ResourcesController],
providers: [Logger],
})
export class ResourcesModule {}
......@@ -11,6 +11,7 @@ export const NOT_FOUND = new NotFoundException();
export const CONFLICT = new ConflictException();
export const BAD_REQUEST = new BadRequestException();
export const INTERNAL = new InternalServerErrorException();
export const UNPROCESSABLE_ENTITY = new UnprocessableEntityException();
export const BAD_TRACKING_STATE = (badState: string) =>
new UnprocessableEntityException(`Unknown state [${badState}]`);
export const CUSTOM = (reason: string, errorStatus: number) =>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment