- add file.controller.ts and File.ts for downloading files from server

- allow Get and Post form Oia/Index method
This commit is contained in:
Arno Kaimbacher 2022-11-09 17:02:18 +01:00
parent 44688ac806
commit 83685b68ed
5 changed files with 133 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import HomeRoutes from "./routes/home.routes.js";
import { initDB } from "./config/db.config"; import { initDB } from "./config/db.config";
import { DatasetController } from "./controllers/dataset.controller"; import { DatasetController } from "./controllers/dataset.controller";
import { OaiController } from "./controllers/oai.controller"; import { OaiController } from "./controllers/oai.controller";
import { FileController } from "./controllers/file.controller";
import * as path from 'path'; import * as path from 'path';
export class App extends Server { export class App extends Server {
@ -54,7 +55,7 @@ export class App extends Server {
// addroutes // addroutes
// this.app.use('/api/dataset', DatasetRoutes); // this.app.use('/api/dataset', DatasetRoutes);
super.addControllers([new DatasetController(), new OaiController()]); super.addControllers([new DatasetController(), new OaiController(), new FileController()]);
this.app.use("/api/", HomeRoutes); this.app.use("/api/", HomeRoutes);
this.app.get("/", (request, response) => { this.app.get("/", (request, response) => {

View File

@ -0,0 +1,54 @@
import { Controller, Get } from "@overnightjs/core";
import { File } from "../models/init-models.js";
import { StatusCodes } from "http-status-codes";
import { Request, Response } from "express";
import * as path from "path";
import * as fs from "fs";
@Controller("file")
export class FileController {
constructor() {}
@Get("download/:id")
public async findOne(req: Request, res: Response) {
const id = req.params.id;
const file = await File.findOne({
where: { id: id },
});
if (file) {
let filePath = "/storage/app/public/" + file.path_name;
const ext = path.extname(filePath);
let fileName = file.label + ext;
try {
fs.accessSync(filePath, fs.constants.R_OK | fs.constants.W_OK);
// console.log("can read/write:", path);
res.set({
"Cache-Control": "no-cache private",
"Content-Description": "File Transfer",
"Content-Type": file.mime_type,
"Content-Disposition": "inline; filename=" + fileName,
"Content-Transfer-Encoding": "binary",
});
res.status(StatusCodes.OK).sendFile(filePath);
} catch (err) {
// console.log("no access:", path);
res.status(StatusCodes.NOT_FOUND).send({
message: `File with id ${id} doesn't exist on file server`,
});
}
// res.status(StatusCodes.OK).sendFile(filePath, (err) => {
// // res.setHeader("Content-Type", "application/json");
// // res.removeHeader("Content-Disposition");
// res.status(StatusCodes.NOT_FOUND).send({
// message: `File with id ${id} doesn't exist on file server`,
// });
// });
} else {
res.status(StatusCodes.NOT_FOUND).send({
message: `Cannot find File with id=${id}.`,
});
}
}
}

View File

@ -1,4 +1,4 @@
import { Controller, Get } from "@overnightjs/core"; import { Controller, Get, Post } from "@overnightjs/core";
import Sequelize from "sequelize"; import Sequelize from "sequelize";
import { NextFunction, Request, Response } from "express"; import { NextFunction, Request, Response } from "express";
import { StatusCodes } from "http-status-codes"; import { StatusCodes } from "http-status-codes";
@ -55,6 +55,7 @@ export class OaiController {
this.configuration = new Configuration(); this.configuration = new Configuration();
} }
@Post("")
@Get("") @Get("")
public async index(request: Request, response: Response, next: NextFunction) { public async index(request: Request, response: Response, next: NextFunction) {
this.xml = create( this.xml = create(
@ -87,7 +88,6 @@ export class OaiController {
try { try {
await this.handleRequest(oaiRequest, request); await this.handleRequest(oaiRequest, request);
} catch (error) { } catch (error) {
// return next(error);
if (error instanceof OaiModelException) { if (error instanceof OaiModelException) {
this.xsltParameter["oai_error_code"] = error.oaiCode; this.xsltParameter["oai_error_code"] = error.oaiCode;
this.xsltParameter["oai_error_message"] = error.message; this.xsltParameter["oai_error_message"] = error.message;
@ -151,7 +151,7 @@ export class OaiController {
// $this->loadStyleSheet('datasetxml2oai-pmh.xslt'); // $this->loadStyleSheet('datasetxml2oai-pmh.xslt');
// Set response time // Set response time
const now: dayjs.Dayjs = dayjs(); const now: Dayjs = dayjs();
this.xsltParameter["responseDate"] = now.format("YYYY-MM-DDThh:mm:ss[Z]"); this.xsltParameter["responseDate"] = now.format("YYYY-MM-DDThh:mm:ss[Z]");
this.xsltParameter["unixTimestamp"] = now.unix(); this.xsltParameter["unixTimestamp"] = now.unix();
@ -182,12 +182,8 @@ export class OaiController {
this.handleIllegalVerb(); this.handleIllegalVerb();
} }
} else { } else {
// const err = new HttpException(404, 'Not Found')
// next(err);
// try { // try {
// console.log("Async code example.") // console.log("Async code example.")
// const err = new HttpException(404, 'Not Found');
const err = new PageNotFoundException("verb not found"); const err = new PageNotFoundException("verb not found");
throw err; throw err;
// } catch (error) { // manually catching // } catch (error) { // manually catching
@ -363,21 +359,8 @@ export class OaiController {
let totalIds = 0; let totalIds = 0;
let start = maxRecords + 1; let start = maxRecords + 1;
let reldocIds: (number | null)[] = []; let reldocIds: (number | null)[] = [];
let metadataPrefix = null; let metadataPrefix = null;
// const tokenWorker = new TokenWorker(86400);
// await tokenWorker.connect();
// $tokenWorker->setResumptionPath($tokenTempPath);
// const url = process.env.REDIS_URL || "redis://redis:6379";
// const redisClient = createClient({
// url
// });
// redisClient.on('error', (error) => {
// const err = new InternalServerErrorException("Error occured while connecting or accessing redis server'");
// throw err;
// });
// resumptionToken is defined // resumptionToken is defined
if ("resumptionToken" in oaiRequest) { if ("resumptionToken" in oaiRequest) {
const resParam = oaiRequest["resumptionToken"]; //e.g. "158886496600000" const resParam = oaiRequest["resumptionToken"]; //e.g. "158886496600000"

71
src/models/File.ts Normal file
View File

@ -0,0 +1,71 @@
import { Model, DataTypes, InferAttributes, InferCreationAttributes, CreationOptional } from "sequelize";
import sequelizeConnection from "../config/db.config";
class File extends Model<InferAttributes<File>, InferCreationAttributes<File>> {
// id can be undefined during creation when using `autoIncrement`
declare id: CreationOptional<number>;
declare path_name: string; // not nullable fields
declare label: string | null;
declare comment: string | null;
declare mime_type: string;
declare language: string | null;
declare file_size: bigint;
declare visible_in_frontdoor: boolean;
declare visible_in_oai: boolean;
declare sort_order: number;
// createdAt can be undefined during creation
declare created_at: CreationOptional<Date>;
// updatedAt can be undefined during creation
declare updated_at: CreationOptional<Date>;
}
File.init(
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
},
path_name: {
type: DataTypes.STRING(100),
allowNull: false,
},
label: DataTypes.STRING(100),
comment: DataTypes.STRING(255),
mime_type: {
type: DataTypes.STRING(255),
allowNull: false,
},
language: DataTypes.STRING(3),
file_size: {
type: DataTypes.BIGINT,
allowNull: false,
},
visible_in_frontdoor: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
visible_in_oai: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
},
sort_order: {
type: DataTypes.INTEGER,
allowNull: false,
},
created_at: DataTypes.DATE,
updated_at: DataTypes.DATE,
},
{
createdAt: "created_at",
updatedAt: "updated_at",
tableName: "document_files",
sequelize: sequelizeConnection,
},
);
export default File;

View File

@ -11,13 +11,14 @@ import Person from "./Person";
import { Sequelize } from "sequelize"; import { Sequelize } from "sequelize";
import Subject from "./subject.model.js"; import Subject from "./subject.model.js";
import Project from "./Project"; import Project from "./Project";
import File from "./file.model.js"; // import File from "./file.model.js";
import File from "./File";
import Identifier from "./Identifier"; import Identifier from "./Identifier";
import DocumentXmlCache from "./DocumentXmlCache"; import DocumentXmlCache from "./DocumentXmlCache";
const dbContext = initModels(); const dbContext = initModels();
export { Dataset, Title, Abstract, User, Person, Subject, Coverage, License, Project, Identifier, DocumentXmlCache }; export { Dataset, Title, Abstract, User, Person, Subject, Coverage, License, Project, Identifier, DocumentXmlCache, File };
export default dbContext; export default dbContext;
export function initModels() { export function initModels() {