From 5419d2eaa0bbc9b828db934d7e657430e92ed5c6 Mon Sep 17 00:00:00 2001 From: OldHawk Date: Fri, 14 Jul 2017 12:29:57 +0800 Subject: [PATCH] feat(forums): add attach download route & method --- .../controllers/forums.server.controller.js | 217 ++++++++++++++++++ .../server/policies/forums.server.policy.js | 2 + .../server/routes/forums.server.routes.js | 5 + 3 files changed, 224 insertions(+) diff --git a/modules/forums/server/controllers/forums.server.controller.js b/modules/forums/server/controllers/forums.server.controller.js index 22396db2..6f41bc70 100644 --- a/modules/forums/server/controllers/forums.server.controller.js +++ b/modules/forums/server/controllers/forums.server.controller.js @@ -7,6 +7,8 @@ var path = require('path'), config = require(path.resolve('./config/config')), mongoose = require('mongoose'), errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller')), + multer = require('multer'), + fs = require('fs'), moment = require('moment'), User = mongoose.model('User'), Forum = mongoose.model('Forum'), @@ -156,6 +158,31 @@ exports.postNewTopic = function (req, res) { topic.forum = forum; topic.user = req.user; + //move temp torrent file to dest directory + req.body._uImage.forEach(function (f) { + var oldPath = config.uploads.attach.file.temp + f.filename; + var newPath = config.uploads.attach.file.dest + f.filename; + move(oldPath, newPath, function (err) { + if (err) { + console.log(err); + } + }); + }); + req.body._attach.forEach(function (f) { + var oldPath = config.uploads.attach.file.temp + f.filename; + var newPath = config.uploads.attach.file.dest + f.filename; + move(oldPath, newPath, function (err) { + if (err) { + console.log(err); + } + }); + }); + + //replace content path + var regex = new RegExp('/modules/forums/client/attach/temp/', 'g'); + topic.content = topic.content.replace(regex, '/modules/forums/client/attach/'); + + //save topic topic.save(function (err) { if (err) { return res.status(422).send({ @@ -172,6 +199,39 @@ exports.postNewTopic = function (req, res) { }); }; +/** + * move file + * @param oldPath + * @param newPath + * @param callback + */ +function move(oldPath, newPath, callback) { + fs.rename(oldPath, newPath, function (err) { + if (err) { + if (err.code === 'EXDEV') { + copy(); + } else { + callback(err); + } + return; + } + callback(); + }); + + function copy() { + var readStream = fs.createReadStream(oldPath); + var writeStream = fs.createWriteStream(newPath); + + readStream.on('error', callback); + writeStream.on('error', callback); + + readStream.on('close', function () { + fs.unlink(oldPath, callback); + }); + readStream.pipe(writeStream); + } +} + /** * read readTopic * @param req @@ -338,11 +398,36 @@ exports.postNewReply = function (req, res) { var reply = new Reply(req.body); reply.user = req.user; + //replace content path + var regex = new RegExp('/modules/forums/client/attach/temp/', 'g'); + reply.content = reply.content.replace(regex, '/modules/forums/client/attach/'); + topic._replies.push(reply); topic.replyCount++; topic.lastReplyAt = Date.now(); topic.lastUser = req.user; + //move temp torrent file to dest directory + req.body._uImage.forEach(function (f) { + var oldPath = config.uploads.attach.file.temp + f.filename; + var newPath = config.uploads.attach.file.dest + f.filename; + move(oldPath, newPath, function (err) { + if (err) { + console.log(err); + } + }); + }); + req.body._attach.forEach(function (f) { + var oldPath = config.uploads.attach.file.temp + f.filename; + var newPath = config.uploads.attach.file.dest + f.filename; + move(oldPath, newPath, function (err) { + if (err) { + console.log(err); + } + }); + }); + + //save topic topic.save(function (err) { if (err) { return res.status(422).send({ @@ -424,6 +509,138 @@ exports.deleteReply = function (req, res) { }); }; +/** + * attachUpload + * @param req + * @param res + */ +exports.attachUpload = function (req, res) { + var user = req.user; + var createUploadAttachFilename = require(path.resolve('./config/lib/multer')).createUploadAttachFilename; + var getUploadAttachDestination = require(path.resolve('./config/lib/multer')).getUploadAttachDestination; + var attachInfo = {}; + + var storage = multer.diskStorage({ + destination: getUploadAttachDestination, + filename: createUploadAttachFilename + }); + + var upload = multer({ + storage: storage, + //fileFilter: fileFilter, + limits: config.uploads.attach.file.limits + }).single('newAttachFile'); + + if (user) { + uploadFile() + .then(function () { + res.status(200).send(attachInfo); + }) + .catch(function (err) { + res.status(422).send(err); + console.log(err); + + if (req.file && req.file.filename) { + var newfile = config.uploads.attach.file.temp + req.file.filename; + if (fs.existsSync(newfile)) { + console.log(err); + console.log('ERROR: DELETE TEMP ATTACH FILE: ' + newfile); + fs.unlinkSync(newfile); + } + } + }); + } else { + res.status(401).send({ + message: 'User is not signed in' + }); + } + + function uploadFile() { + return new Promise(function (resolve, reject) { + upload(req, res, function (uploadError) { + if (uploadError) { + var message = errorHandler.getErrorMessage(uploadError); + + if (uploadError.code === 'LIMIT_FILE_SIZE') { + message = 'Attach file too large. Maximum size allowed is ' + (config.uploads.attach.file.limits.fileSize / (1024 * 1024)).toFixed(2) + ' Mb files.'; + } + + reject(message); + } else { + attachInfo.filename = req.file.filename; + resolve(); + } + }); + }); + } +}; + +/** + * attachDownload + * @param req + * @param res + */ +exports.attachDownload = function (req, res) { + var topic = req.topic; + var filePath = undefined; + + if (req.params.replyId) { + topic._replies.forEach(function (rep) { + if (rep._id.equals(req.params.replyId)) { + rep._attach.forEach(function (at) { + if (at._id.equals(req.query.attachId)) { + at.downCount++; + filePath = config.uploads.attach.file.dest + at.filename; + + topic.markModified('_replies'); + topic.save(); + } + }); + } + }); + } else { + topic._attach.forEach(function (at) { + if (at._id.equals(req.query.attachId)) { + at.downCount++; + filePath = config.uploads.attach.file.dest + at.filename; + + topic.save(); + } + }); + } + return downFile(filePath); + + function downFile(filePath) { + if (!filePath) { + res.status(422).send({ + message: 'FILE_DOES_NOT_FINDED' + }); + } + + fs.exists(filePath, function (exists) { + if (exists) { + var stat = fs.statSync(filePath); + + try { + //res.set('Content-Type', 'application/x-bittorrent'); + res.set('Content-Disposition', 'attachment; filename=' + req.params.filename); + res.set('Content-Length', stat.size); + + fs.createReadStream(filePath).pipe(res); + } catch (err) { + res.status(422).send({ + message: 'DOWNLOAD_FAILED' + }); + } + } else { + res.status(422).send({ + message: 'FILE_DOES_NOT_EXISTS' + }); + } + }); + } +}; + /** * Invitation middleware */ diff --git a/modules/forums/server/policies/forums.server.policy.js b/modules/forums/server/policies/forums.server.policy.js index 9df66d82..0cbb2777 100644 --- a/modules/forums/server/policies/forums.server.policy.js +++ b/modules/forums/server/policies/forums.server.policy.js @@ -19,6 +19,8 @@ exports.invokeRolesPolicies = function () { allows: [ {resources: '/api/forums', permissions: '*'}, {resources: '/api/attach/upload', permissions: '*'}, + {resources: '/api/attach/:topicId', permissions: '*'}, + {resources: '/api/attach/:topicId/:replyId', permissions: '*'}, {resources: '/api/forums/:forumId', permissions: '*'}, {resources: '/api/topics/:forumId', permissions: '*'}, {resources: '/api/topics/:forumId/:topicId', permissions: '*'}, diff --git a/modules/forums/server/routes/forums.server.routes.js b/modules/forums/server/routes/forums.server.routes.js index 94a4de6c..3b9fc8a2 100644 --- a/modules/forums/server/routes/forums.server.routes.js +++ b/modules/forums/server/routes/forums.server.routes.js @@ -13,6 +13,11 @@ module.exports = function (app) { app.route('/api/attach/upload').all(forumsPolicy.isAllowed) .post(forums.attachUpload); + app.route('/api/attach/:topicId').all(forumsPolicy.isAllowed) + .get(forums.attachDownload); + app.route('/api/attach/:topicId/:replyId').all(forumsPolicy.isAllowed) + .get(forums.attachDownload); + app.route('/api/forums/:forumId').all(forumsPolicy.isAllowed) .get(forums.read);