Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: backend implementing attachment server interface #197

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,15 @@ Configured services at:
/origoserver/attachments/ngp/dpdocuments/something-like-the-layername/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/attachments

/origoserver/attachments/ngp/dpdocuments/something-like-the-layername/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/attachments/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

- Attachment - list, get, add and delete files to features

Configure attachment in conf/config.js

/origoserver/attachment/{something-like-the-layername}/{a unique identifier}/attachments

/origoserver/attachment/{something-like-the-layername}/{a unique identifier}/attachments/{uuid}

/origoserver/attachment/{something-like-the-layername}/{a unique identifier}/addAttachment

/origoserver/attachment/{something-like-the-layername}/{a unique identifier}/deleteAttachments
3 changes: 3 additions & 0 deletions conf/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,5 +148,8 @@ module.exports = {
grant_type: 'client_credentials',
scope: 'am_application_scope default',
query: '{"feature.typ": {"eq": "detaljplan"}, "detaljplan.objektidentitet": {"eq": "$planid$"}, "detaljplan.status": {"in": ["laga kraft"]}}'
},
attachment: {
filepath: "C:\\attachment\\"
}
}
118 changes: 118 additions & 0 deletions handlers/attachment/attachments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
var conf = require('../../conf/config');
var ex = require('express');
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const getUuid = require('uuid-by-string');

let configOptions = {};
const router = ex.Router();

if (conf['attachment']) {
configOptions = Object.assign({}, conf['attachment']);
}

/**
* List all attachments belonging to this object and group
*
* @function
* @name listAttachments
* @kind function
* @param {any} req
* @param {any} res
* @param {any} next
* @returns {Promise<void>}
*/
function listAttachments(req, res, next) {
const dir = path.join(configOptions.filepath, req.params.layer, req.params.object);
let fileInfos = [];
// Check directory for files
if (!fs.existsSync(dir)) {
// No files found return empty
res.json({ "attachmentInfos": fileInfos });
} else {
const groups = fs.readdirSync(dir);
groups.forEach(group => {
const groupPath = path.join(dir, group);
const fileNames = fs.readdirSync(groupPath);
// Go through the files in directory
fileNames.forEach(filename => {
const filePath = path.join(groupPath, filename);
const fileInfo = {
"id": getUuid(`${group}_${filename}`, 5), // Create a stable uuid for the file from the group and filename, uuid version 5
"contentType": mime.lookup(filename),
"size": fs.statSync(filePath).size,
"name": filename,
"group": group
};
fileInfos.push(fileInfo);
});
});
res.json({ "attachmentInfos": fileInfos });
}
}

/**
* Get the the document with id from a specific object and group
*
* @function
* @name fetchDoc
* @kind function
* @param {any} req
* @param {any} res
* @param {any} next
* @returns {Promise<void>}
*/
function fetchDoc(req, res, next) {
const dir = path.join(configOptions.filepath, req.params.layer, req.params.object);
const groups = fs.readdirSync(dir);
groups.forEach(group => {
const groupPath = path.join(dir, group);
const fileNames = fs.readdirSync(groupPath);

fileNames.forEach(filename => {
if (getUuid(`${group}_${filename}`, 5) === req.params.id) {
const filePath = path.join(dir, group, filename);
res.sendFile(filePath);
}
});
});
}

/**
* Delete a attachment file identified by uuid
*
* @function
* @name deleteAttachment
* @kind function
* @param {any} req
* @param {any} res
* @param {any} next
* @returns {void}
*/
function deleteAttachment(req, res, next) {
const result = { "deleteAttachmentResults": [] };
const idsToDelete = req.body.attachmentIds.split(',');
const dir = path.join(configOptions.filepath, req.params.layer, req.params.object);

if (fs.existsSync(dir)) {
const groups = fs.readdirSync(dir);
groups.forEach(group => {
const fileNames = fs.readdirSync(path.join(dir, group));
fileNames.forEach(filename => {
if (idsToDelete.includes(getUuid(`${group}_${filename}`, 5))) {
const filePath = path.join(dir, group, filename);
fs.rmSync(filePath, { recursive: true });
result.deleteAttachmentResults.push({
"objectId": getUuid(`${group}_${filename}`, 5), // Create a stable uuid for the file from the group and filename, uuid version 5
"globalId": null,
"success": true
});
}
});
});
}
res.json(result);
}

module.exports = { listAttachments, fetchDoc, deleteAttachment };
56 changes: 56 additions & 0 deletions handlers/attachment/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
var conf = require('../../conf/config');
const express = require('express');
const fs = require('fs');
const path = require('path');
const { listAttachments, fetchDoc, deleteAttachment } = require('./attachments');
const multer = require('multer');
const getUuid = require('uuid-by-string');
const attachmentRouter = express.Router();

// Let the upload middleware buffer the file in memory
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

let configOptions = {};

if (conf['attachment']) {
configOptions = Object.assign({}, conf['attachment']);
}

attachmentRouter.get('/:layer/:object/attachments/', listAttachments);
attachmentRouter.get('/:layer/:object/attachments/:id', fetchDoc);
attachmentRouter.post('/:layer/:object/deleteAttachments/', deleteAttachment);
attachmentRouter.post('/:layer/:object/addAttachment', upload.single('attachment'), function (req, res, next) {
const dir = path.join(configOptions.filepath, req.params.layer, req.params.object, req.body.group);
// Create directory if doesn't already exists
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
if (typeof req.file !== 'undefined') {
// Get the filename and convert to utf8 from latin1
const fileName = path.join(dir, Buffer.from(req.file.originalname, 'latin1').toString('utf8'));
// Write the file to disc
fs.writeFileSync(fileName, req.file.buffer);
// Create response object to send back after successful saved
const retval = {
"addAttachmentResult": {
"objectId": getUuid(`${req.body.group}_${fileName}`, 5),
"globalId": null,
"success": true
}
}
res.json(retval);
} else {
// Something went wrong with posting the file
const retval = {
"addAttachmentResult": {
"objectId": null,
"globalId": null,
"success": false
}
}
res.json(retval);
}
});

module.exports = attachmentRouter;
Loading