diff --git a/src/backend/middlewares/MetaFileMWs.ts b/src/backend/middlewares/MetaFileMWs.ts index 3321fd0e..d06f4992 100644 --- a/src/backend/middlewares/MetaFileMWs.ts +++ b/src/backend/middlewares/MetaFileMWs.ts @@ -1,7 +1,8 @@ import {NextFunction, Request, Response} from 'express'; import * as fs from 'fs'; -import { Config } from '../../common/config/private/Config'; -import { GPXProcessing } from '../model/fileprocessing/GPXProcessing'; +import {Config} from '../../common/config/private/Config'; +import {GPXProcessing} from '../model/fileprocessing/GPXProcessing'; +import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; export class MetaFileMWs { public static async compressGPX( @@ -17,22 +18,31 @@ export class MetaFileMWs { return res.redirect(req.originalUrl.slice(0, -1 * '\\bestFit'.length)); } const fullPath = req.resultPipe as string; + try { + const compressedGPX = GPXProcessing.generateConvertedPath( + fullPath, + ); - const compressedGPX = GPXProcessing.generateConvertedPath( - fullPath, - ); + // check if converted photo exist + if (fs.existsSync(compressedGPX) === true) { + req.resultPipe = compressedGPX; + return next(); + } - // check if converted photo exist - if (fs.existsSync(compressedGPX) === true) { - req.resultPipe = compressedGPX; - return next(); + if (Config.MetaFile.GPXCompressing.onTheFly === true) { + req.resultPipe = await GPXProcessing.compressGPX(fullPath); + return next(); + } + } catch (err) { + + return next( + new ErrorDTO( + ErrorCodes.METAFILE_ERROR, + 'Error during compressingGPX: ' + fullPath, + err + ) + ); } - - if (Config.MetaFile.GPXCompressing.onTheFly === true) { - req.resultPipe = await GPXProcessing.compressGPX(fullPath); - return next(); - } - // not converted and won't be now return res.redirect(req.originalUrl.slice(0, -1 * '\\bestFit'.length)); } diff --git a/src/backend/model/fileprocessing/GPXProcessing.ts b/src/backend/model/fileprocessing/GPXProcessing.ts index 6b050dfa..49b71179 100644 --- a/src/backend/model/fileprocessing/GPXProcessing.ts +++ b/src/backend/model/fileprocessing/GPXProcessing.ts @@ -82,48 +82,49 @@ export class GPXProcessing { await fsp.mkdir(outDir, {recursive: true}); const gpxStr = await fsp.readFile(filePath); const gpxObj = await (new xml2js.Parser()).parseStringPromise(gpxStr); - const items: gpxEntry[] = gpxObj.gpx.trk[0].trkseg[0].trkpt; + const items: gpxEntry[] = gpxObj.gpx?.trk?.[0]?.trkseg[0]?.trkpt; - const distance = (entry1: gpxEntry, entry2: gpxEntry) => { - const lat1 = parseFloat(entry1.$.lat); - const lon1 = parseFloat(entry1.$.lon); - const lat2 = parseFloat(entry2.$.lat); - const lon2 = parseFloat(entry2.$.lon); + if (items) { // only compress paths + const distance = (entry1: gpxEntry, entry2: gpxEntry) => { + const lat1 = parseFloat(entry1.$.lat); + const lon1 = parseFloat(entry1.$.lon); + const lat2 = parseFloat(entry2.$.lat); + const lon2 = parseFloat(entry2.$.lon); - // credits to: https://www.movable-type.co.uk/scripts/latlong.html - const R = 6371e3; // metres - const φ1 = lat1 * Math.PI / 180; // φ, λ in radians - const φ2 = lat2 * Math.PI / 180; - const Δφ = (lat2 - lat1) * Math.PI / 180; - const Δλ = (lon2 - lon1) * Math.PI / 180; + // credits to: https://www.movable-type.co.uk/scripts/latlong.html + const R = 6371e3; // metres + const φ1 = lat1 * Math.PI / 180; // φ, λ in radians + const φ2 = lat2 * Math.PI / 180; + const Δφ = (lat2 - lat1) * Math.PI / 180; + const Δλ = (lon2 - lon1) * Math.PI / 180; - const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + - Math.cos(φ1) * Math.cos(φ2) * - Math.sin(Δλ / 2) * Math.sin(Δλ / 2); - const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + + Math.cos(φ1) * Math.cos(φ2) * + Math.sin(Δλ / 2) * Math.sin(Δλ / 2); + const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - const d = R * c; // in metres - return d; - }; - const gpxEntryFilter = (value: gpxEntry, i: number, list: gpxEntry[]) => { - if (i === 0 || i >= list.length - 1) { // always keep the first and last items - return true; - } - const timeDelta = (Date.parse(list[i].time[0]) - Date.parse(list[i - 1].time[0])); // mill sec. - const dist = distance(list[i - 1], list[i]); // meters + const d = R * c; // in metres + return d; + }; + const gpxEntryFilter = (value: gpxEntry, i: number, list: gpxEntry[]) => { + if (i === 0 || i >= list.length - 1) { // always keep the first and last items + return true; + } + const timeDelta = (Date.parse(list[i].time[0]) - Date.parse(list[i - 1].time[0])); // mill sec. + const dist = distance(list[i - 1], list[i]); // meters - return !(timeDelta < Config.MetaFile.GPXCompressing.minTimeDistance && - dist < Config.MetaFile.GPXCompressing.minDistance); - }; - - gpxObj.gpx.trk[0].trkseg[0].trkpt = items.filter(gpxEntryFilter).map((v) => { - v.$.lon = parseFloat(v.$.lon).toFixed(6); - v.$.lat = parseFloat(v.$.lat).toFixed(6); - delete v.ele; - delete v.extensions; - return v; - }); + return !(timeDelta < Config.MetaFile.GPXCompressing.minTimeDistance && + dist < Config.MetaFile.GPXCompressing.minDistance); + }; + gpxObj.gpx.trk[0].trkseg[0].trkpt = items.filter(gpxEntryFilter).map((v) => { + v.$.lon = parseFloat(v.$.lon).toFixed(6); + v.$.lat = parseFloat(v.$.lat).toFixed(6); + delete v.ele; + delete v.extensions; + return v; + }); + } await fsp.writeFile(outPath, (new xml2js.Builder({renderOpts: {pretty: false}})).buildObject(gpxObj)); return outPath; diff --git a/src/common/entities/Error.ts b/src/common/entities/Error.ts index 8b98ed3d..c8b9b00a 100644 --- a/src/common/entities/Error.ts +++ b/src/common/entities/Error.ts @@ -7,24 +7,25 @@ export enum ErrorCodes { PERMISSION_DENIED = 4, CREDENTIAL_NOT_FOUND = 5, - USER_CREATION_ERROR = 6, + USER_CREATION_ERROR = 20, - GENERAL_ERROR = 7, - THUMBNAIL_GENERATION_ERROR = 8, - PHOTO_GENERATION_ERROR = 9, - PERSON_ERROR = 10, - SERVER_ERROR = 11, + GENERAL_ERROR = 31, + THUMBNAIL_GENERATION_ERROR = 32, + PHOTO_GENERATION_ERROR = 33, + PERSON_ERROR = 34, + METAFILE_ERROR = 35, + SERVER_ERROR = 36, - USER_MANAGEMENT_DISABLED = 12, + USER_MANAGEMENT_DISABLED = 40, - INPUT_ERROR = 13, + INPUT_ERROR = 50, - SETTINGS_ERROR = 14, - TASK_ERROR = 15, - JOB_ERROR = 16, - LocationLookUp_ERROR = 17, + SETTINGS_ERROR = 60, + TASK_ERROR = 61, + JOB_ERROR = 62, + LocationLookUp_ERROR = 63, - ALBUM_ERROR = 18, + ALBUM_ERROR = 70, } export class ErrorDTO {