Skip to content

Instantly share code, notes, and snippets.

@samguergen
Created February 13, 2019 20:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save samguergen/6ac85d0b4acb3ccd94391f78b13bd6e4 to your computer and use it in GitHub Desktop.
Save samguergen/6ac85d0b4acb3ccd94391f78b13bd6e4 to your computer and use it in GitHub Desktop.
File Upload functionality files isolated from the widget repo
var express = require('express');
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var app = express();
const MongoClient = require('mongodb').MongoClient;
var mongo = require('mongodb');
var session = require('express-session');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var env = require(__dirname + '/env-vars.js');
var gmail_login = env.gmail_login;
var gmail_pass = env.gmail_pass;
var db;
var http = require('http');
var request=require('request');
var _ =require('lodash');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' })
var multipart = require('connect-multiparty');
var formidable = require('express-formidable');
var fs = require('fs');
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use(express.json()); //convert req to json
app.use(express.static(__dirname + '/app'));
app.use(session({secret: "Sam is awesome"}));
// app.use(formidable());
app.use(bodyParser.json()); // Configures bodyParser to accept JSON
app.use(bodyParser.urlencoded({
extended: false
}));
var allPages = ['/home','/portfolio', '/timesheets', '/timesheet', '/documents','/shift-scheduler','/comments','/blog-thumbnail'];
MongoClient.connect('mongodb://samguergen:samanthics2504@ds119662.mlab.com:19662/widgets', function(err, client) {
if (err) {
console.log('db not connecting, but inside mongo block - 1', err);
};
db = client.db('widgets');
console.log('inside first mongo block');
app.get('/getTimesheets', function (req,res) {
db.collection('timesheets').find().toArray(function (err, result) {
res.send(result);
})
});
app.post('/addTimesheet', function (req,res) {
console.log('inside timesheet add')
var timesheet = req.body.timesheet;
console.log('ts to be saved, received from backend is ', timesheet);
db.collection('timesheets').save(timesheet, function(err, result){
if (err) { return console.log('connecting to db, but not saving obj', err);}
console.log('ts saved to database');
res.send(result);
})
});
app.delete('/deleteTimesheet', function (req,res) {
var timesheetId = req.query.timesheetId;
console.log('ts to be deleted, received from backend is ', timesheetId)
db.collection('timesheets').deleteOne({_id: new mongo.ObjectId(timesheetId)}, function(err, result){
if (err) { throw new Error('No record found. ', err) };
console.log('timesheet has been removed, i think');
res.send(result);
});
}); // end of deleteagendaevent request
app.get('/getDocuments', formidable(), function (req,res) {
db.collection('documents').find().toArray(function (err, result) {
res.send(result);
})
}); // end of /getRidesData get request
app.post('/uploadFiles', formidable(), function(req, res) {
console.log('uploadFiles from backend is ', req.files);
var binaryLocation = req.files.file.path;
var fileName = req.files.file.name;
console.log('file name is ', fileName);
var binaryData = fs.readFileSync(binaryLocation);
var theFile = {};
theFile.data = binaryData
theFile.name = fileName;
theFile.category = 'all';
theFile.categoryGeneral = 'all';
var tableName = req.query.tableName;
console.log('theFile is ', theFile);
db.collection('documents').save(theFile, function(err, result){
if (err) { return console.log('connecting to db, but not saving obj', err);}
console.log('doc saved to database');
res.send(result);
})
});
app.delete('/removeFile', formidable(), function (req,res) {
console.log('inside removeFile, queries are ', req.query.fileId);
var fileId = req.query.fileId;
db.collection('documents').deleteOne({_id: new mongo.ObjectId(fileId)}, function(err, result){
if (err) { throw new Error('No record found. ', err) };
console.log('file has been removed, i think');
res.send(result);
});
}); // end of /removeFile delete request
app.put('/updateCategory', function (req,res) {
var fileName = req.body.fileName;
var categoryDbName = req.body.categoryDbName;
var fileId = req.body.fileId;
console.log('file name is ', fileName, 'categoryDbName ', categoryDbName, 'fileId ', fileId);
var myQuery = {_id: new mongo.ObjectId(fileId)};
var newValues = {
$set: {
category: categoryDbName
}
};
db.collection('documents').findAndModify(myQuery, [['_id','asc']], newValues, {}, function(err, result){
if (err) { throw new Error('No record found. ', err) };
console.log('record has been updated, i think');
res.send(result);
});
}); // end of /updateCategory put request
app.get('/viewWeeklyCalendarEvents', function (req,res) {
db.collection('weekly-calendar').find().toArray(function (err, result) {
res.send(result);
})
}); // end of /viewRISCalendarEvents get request
app.post('/addWeeklyCalendarEvent', function (req,res) {
var newEvent = req.body.newEvent;
console.log('event to be saved, received from backend is ', newEvent);
db.collection('weekly-calendar').save(newEvent, function(err, result){
if (err) { return console.log('connecting to db, but not saving obj', err);}
console.log('event saved to database', result);
res.send(result);
})
});
app.delete('/deleteWeeklyCalendarEvent', function (req,res) {
var eventId = req.query.eventId;
console.log('event to be deleted, received from backend is ', eventId)
db.collection('weekly-calendar').deleteOne({_id: new mongo.ObjectId(eventId)}, function(err, result){
if (err) { throw new Error('No record found. ', err) };
console.log('event has been removed');
res.send(result);
});
}); // end of deleteagendaevent request
app.get('/getComments', function (req,res) {
db.collection('comments').find().toArray(function (err, result) {
res.send(result);
})
}); // end of /getComments get request
app.post('/addComment', function (req,res) {
var comment = req.body.comment;
console.log('comment to be saved, received from backend is ', comment);
db.collection('comments').save(comment, function(err, result){
if (err) { return console.log('connecting to db, but not saving obj', err);}
console.log('comment saved to database');
res.send(result);
})
});
app.delete('/deleteComment', function (req,res) {
var commentId = req.query.commentId;
console.log('comment to be deleted, received from backend is ', commentId)
db.collection('comments').deleteOne({_id: new mongo.ObjectId(commentId)}, function(err, result){
if (err) { throw new Error('No record found. ', err) };
console.log('comment has been removed');
res.send(result);
});
}); // end of deleteagendaevent request
app.post('/sendmail', function(req, res){
console.log('inside sendmail, post req', req.body);
let mailOptions = {};
if (req.body){ //private contact form from ITN staff to ITN staff
console.log('sending email without pdf');
mailOptions = {
from: req.body.from, // sender address
to: req.body.to, // list of receivers
subject: req.body.subject, // Subject line
html: req.body.html // html body
};
}
let transporter = nodemailer.createTransport(smtpTransport({
service: "Gmail", // sets automatically host, port and connection security settings
auth: {
user: gmail_login,
pass: gmail_pass
}
})
)
// send mail with defined transport object
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
transporter.close();
});
console.log('after mongo block');
res.end();
});
app.get('/getBlogContent', function(req, res) {
console.log('params are ', req.query)
request.get(req.query.blogURL, function(err,result,body) {
console.log('result is ', result)
res.send(result.body)
});
});
}); //end of main mongodb block
app.use(allPages, function(req, res){
res.sendFile(__dirname + '/app/index.html');
});
app.listen(process.env.PORT || 13270);
<div class="important-docs portal" ng-init="getDocuments()">
<div class="container ta-center">
<h2>Document Library</h2>
<div class="upload-doc">
<button type="button" class="btn btn-lg" ngf-select="upload($file)">Upload a Document</button>
</div><!--upload-doc-->
<div ng-hide="fileUploadsAffiliate" class="loading-msg"><em>Please wait a few seconds while your files are loading on the page.</em></div>
<div class="all-docs">
<h5 class="title">All Documents:</h5>
<div class="dropdown" style="color:black;float:left;margin-left:2%">
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
Filter by category <span class="caret"></span>
</button>
<ul class="dropdown-menu" style="font-size:16px;margin-left: 40%">
<li ng-repeat="category in fileCategories">
<a ng-click="assignFileCategoryFilter(category)"
ng-class="{'no-border': $last}">{{category.name}}
</a>
</li>
</ul>
</div><!--dropodown-->
<h5 ng-show="hideLibrary" class="loading-msg" style="clear:both"><em>{{serverMessage}}</em></h5>
<div><!--all-docs-->
<!-- {{fileCategoryFilter}} -->
<div class="row ta-center"
style="margin:auto;padding:1;clear:both"
ng-hide="hideLibrary">
<div ng-repeat="file in fileUploads"
ng-click="downloadImgFull(file.data)"
class="repeat-img col-sm-3">
<div class="clearfix" ng-if="$index % 4 == 0"></div>
<div class="col-sm-3">
<a ng-click="downloadFile(file, $index)"
ng-attr-id="{{'file-' + $index }}">
<img ng-src="{{file.thumbnailUrlNew}}"/>
</a><br />
<div class="img-legend" style="font-size:14px;margin-top:-30px">
<p class="file-name">
{{file.name}} <br>
<em>category: {{file.category}}</em>
</p>
<button class="btn btn-itn-sm" ng-click="viewEditOptions = !viewEditOptions" ng-hide="viewEditOptions">
Edit
</button>
<div ng-if="viewEditOptions" class="cat-options">
<em>Category: </em> {{file.category}}
<div class="dropdown">
<button class="btn btn-itn-sm dropdown-toggle" type="button" data-toggle="dropdown">
Change Category<span class="caret"></span>
</button>
<ul class="dropdown-menu" style="font-size:14px">
<li ng-repeat="category in fileCategories"><a ng-click="addCategory(file, category); viewEditOptions = false" ng-class="{'no-border': $last}">{{category.name}}</a></li>
</ul>
</div><!--dropdown-->
<button ng-click="removeFile(file); viewEditOptions = false" class="btn-itn-sm" style="margin-top:10px">
Delete file <span class="glyphicon glyphicon-remove"></span>
</button>
</div><!--viewEditOptions-->
</div><!--img-legend-->
</div><!--col-sm-3-->
</div><!--ngRepeat/repeat-img-->
</div><!-- row-->
</div><!--container-->
</div><!--important-docs-->
<div class="back-btn-wrap">
<a ui-sref="documents({filter: docFilter})" class="back-btn">
<h3 style="margin-left:65px">Back to Previous Page</h3>
</a>
<a ui-sref="portal" class="back-btn" style="margin-top:-5%">
<h3>Back to Portal</h3>
</a>
</div>
var myApp = angular.module('myApp');
myApp.controller('FileUploadCtrl', ['$scope', '$transitions', '$http', '$anchorScroll', '$location', '$stateParams', '$timeout', '$state', '$rootScope', '$window', 'FormService', '$sce', 'DataService', '$q', 'FileUploadService', 'Upload', 'LongVariablesService', 'ParseVariablesService', '$filter', function($scope, $transitions, $http, $anchorScroll, $location, $stateParams, $timeout, $state, $rootScope, $window, FormService, $sce, DataService, $q, FileUploadService, Upload, LongVariablesService, ParseVariablesService, $filter) {
console.log('inside file upload controller', $stateParams);
$scope.filePathArray = [];
$scope.getDocuments = function() {
$scope.serverMessage = "Please wait a few seconds while the comments are loading.";
$http.get('/getDocuments').then(function(response){
console.log('response file uploads get ', response)
$scope.fileUploads = response.data;
$scope.fileUploads2 = response.data;
$scope.displayThumbnailImgs(); // once files retrieves, display their thumbnails imgs
$scope.serverMessage = "";
});
};
// upload on file select or drop
$scope.upload = function (file) {
console.log('about to upload ', file, 'file name is ', file.name, 'file format is ', typeof(file));
$scope.serverMessage = "Your file is being uploaded. Please wait.";
$scope.hideLibrary = true;
var fd = new FormData();
fd.append('file', file);
console.log('fd about to be sent is ', fd);
FileUploadService.uploadFileToDB(fd);
//upload service cannot work with promises, so listen to response instead using $rootScope
$rootScope.$on('file upload ok', function(){
console.log('file upload success');
$scope.hideLibrary = true;
$scope.serverMessage = "Your file was successfully uploaded. Reloading page.";
location.reload();
});
};
$scope.removeFile = function(file){
console.log('inside removeFile func, file is ', file, file.name);
$scope.serverMessage = "Your file is being removed. Please wait.";
$scope.hideLibrary = true;
FileUploadService.removeFile(file)
.then(function(response){
$scope.hideLibrary = false;
if (response.status === 200){
console.log('file delete success');
$scope.hideLibrary = true;
$timeout(function(){
$scope.serverMessage = "Your file was successfully removed. Reloading page.";
location.reload();
}, 5000);
} else {
$scope.serverMessage = "There was an error removing your file. Please try again.";
}
}).catch(function(err){
$scope.serverMessage = "There was an error removing your file. Please try again.";
})
};
$scope.addCategory = function(file, category){
console.log('category is ', category, 'file is ', file);
$scope.serverMessage = "The category is being updated. Please wait.";
FileUploadService.addCategory(file, category)
.then(function(response){
$scope.hideLibrary = false;
if (response.status === 200){
console.log('update category success, response is ', response);
$scope.hideLibrary = true;
$timeout(function(){
$scope.serverMessage = "Your file's category has been successfully updated.";
location.reload();
}, 5000);
} else {
$scope.serverMessage = "There was an error updating the category. Please try again.";
}
}).catch(function(err){
$scope.serverMessage = "There was an error updating the category. Please try again.";
})
};
$scope.fileUploads2 = angular.copy($scope.fileUploads);
$scope.assignFileCategoryFilter = function(category){
$scope.fileCategoryFilter = category.dbName;
console.log('inside assignFileCategoryFilter, cat filtered is ', $scope.fileCategoryFilter);
$scope.fileUploads = $filter('filter')($scope.fileUploads2, {category: $scope.fileCategoryFilter});
};
$scope.findFileMimeType = function(file){
var fileFormat = file.name.substr(file.name.length - 3);
fileFormat = fileFormat.toLowerCase();
if (fileFormat === 'png' || fileFormat === 'jpg' || fileFormat === 'peg'){
return 'png'
} else if (fileFormat === 'pdf'){
return 'pdf'
} else if (fileFormat === 'doc' || fileFormat === 'ocx'){
return 'doc'
} else if (fileFormat === 'xls' || fileFormat === 'lsx' || fileFormat === 'xlr' || fileFormat === 'ods'){
return 'excel'
} else if (fileFormat === 'ptx' || fileFormat === 'ppt' || fileFormat === 'pps' || fileFormat === 'odp'){
return 'pptx'
} else if (fileFormat === 'mp3' || fileFormat === 'mp4' || fileFormat === 'mov' || fileFormat === 'mp4' || fileFormat === 'avi' || fileFormat === '3gp' || fileFormat === 'flv' || fileFormat === 'swf' || fileFormat === 'wmv' || fileFormat === '.rm' || fileFormat === 'mp4'){
return 'audiovid'
} else { //if entering new file format, make sure to add icon for thumbnail, as '<fileFormat>-icon.png'
return fileFormat;
}
};
$scope.base64ToImgSrc = function(base64){
if (base64 && $scope.fileMimeType){
var newImgUrl;
if ($scope.fileMimeType === 'png'){
newImgUrl = 'data:image/png;base64,' + base64;
} else if ($scope.fileMimeType === 'blah'){
newImgUrl = 'data:image/blah;base64,' + base64;
}
return newImgUrl;
}
};
$scope.displayThumbnailImgs = function(){
var filePath;
for (var i=0; i < $scope.fileUploads.length; i++){
var file = $scope.fileUploads[i];
$scope.fileMimeType = $scope.findFileMimeType(file);
if ($scope.fileMimeType === 'png'){ //replace icon with thumnail of that img
filePath = $scope.base64ToImgSrc(file.data);
} else { //replace with icon of that file format
filePath = $scope.assetsPath + '/images/icons/' + $scope.fileMimeType + '-icon.png';
}
file.thumbnailUrlNew = filePath;
$scope.filePathArray.push(filePath);
};
// console.log("file path array is ", $scope.filePathArray);
};
$scope.displayThumbnailImg = function(file){
$scope.fileMimeType = $scope.findFileMimeType(file);
if ($scope.fileMimeType === 'png'){ //replace icon with thumnail of that img
$scope.filePath = $scope.base64ToImgSrc(file.data);
} else { //replace with icon of that file format
$scope.filePath = $scope.assetsPath + '/images/icons/' + $scope.fileMimeType + '-icon.png';
}
$scope.filePathArray.push($scope.filePath);
console.log('new filePath is ', $scope.filePath);
console.log('updated file path array ', $scope.filePathArray);
return $scope.filePath;
};
$scope.base64ToPDF = function(formType, formObj) {
console.log('form type is ', formType, 'form obj is ', formObj);
if (formObj && formObj.pdf) {
var base64 = formObj.pdf;
base64 = base64.replace("data:application/pdf;base64,", "");
var binaryImg = window.atob(base64);
var length = binaryImg.length;
var arrayBuffer = new ArrayBuffer(length);
var uintArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < length; i++) {
uintArray[i] = binaryImg.charCodeAt(i);
}
var currentBlob = new Blob([uintArray], {
type: 'application/pdf'
});
$scope.pdfUrl = URL.createObjectURL(currentBlob);
console.log('redirecting to pdf', formType, formObj);
window.open($scope.pdfUrl);
} else {
return $scope.pdfUrl = "This form does not contain a PDF";
}
};
$scope.downloadPNG = function(formObj, idx) {
console.log('inside base64 func');
console.log('form obj is ', formObj);
if (formObj && formObj.data) {
var base64 = formObj.data;
base64 = base64.replace("data:application/png;base64,", "");
var binaryImg = window.atob(base64);
var length = binaryImg.length;
var arrayBuffer = new ArrayBuffer(length);
var uintArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < length; i++) {
uintArray[i] = binaryImg.charCodeAt(i);
}
var currentBlob = new Blob([uintArray], {
type: 'application/png'
});
$window.saveAs(currentBlob, formObj.name);
} else {
return $scope.pdfUrl = "This form does not contain a PDF";
}
};
$scope.downloadPDF = function(formObj) {
console.log('form obj is ', formObj);
if (formObj && formObj.data) {
var base64 = formObj.data.replace("data:application/pdf;base64,", "");
var binaryImg = window.atob(base64);
var arrayBuffer = new ArrayBuffer(binaryImg.length);
var uintArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < length; i++) {
uintArray[i] = binaryImg.charCodeAt(i);
}
var currentBlob = new Blob([uintArray], {
type: 'application/pdf'
});
$scope.pdfUrl = URL.createObjectURL(currentBlob);
// window.location.href = $scope.pdfUrl;
window.open($scope.pdfUrl);
} else {
return $scope.pdfUrl = "This form does not contain a PDF";
}
};
$scope.downloadBLOB = function(file, idx){
var blob = new Blob([s2ab(atob(file.data))], {
type: ''
});
// href = URL.createObjectURL(blob);
$window.saveAs(blob, file.name);
};
$scope.downloadFile = function(file, idx){
var fileMimeType = $scope.findFileMimeType(file);
console.log("file is ", file, 'type is ', fileMimeType);
if (fileMimeType === 'png'){
$scope.downloadPNG(file, idx)
} else if (fileMimeType !== 'png'){
$scope.downloadBLOB(file)
} //audio, video, photoshop, svg
};
$scope.catchFormObj = function() {
$scope.formObj = $stateParams.formObj;
$scope.formObjType = $stateParams.formType;
console.log('formobj is ', $scope.formObj);
};
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
}; //
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
};
}]);
var myApp = angular.module('myApp');
myApp.service('FileUploadService', ['$http','$q','$rootScope', function ($http, $q, $rootScope) {
var self = this;
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
};
this.uploadFileToDB = function(fd){
return $http.post('/uploadFiles', fd, {
headers: {'Content-Type': undefined}
})
.then(function(data){
if (data.status === 200){
console.log('succesfully uploaded file ', data);
$rootScope.$broadcast('file upload ok', data);
} else {
console.log('error uploading file ', data);
$rootScope.$broadcast('file upload error', data);
}
return data;
})
};
this.removeFile = function(file){
console.log('file is ', file, 'id is ', file._id);
return $http.delete('/removeFile', {
params: {
fileId: file._id
}
})
.then(function(data){
if (data.status === 200){
return data;
} else {
throw 500;
}
}).catch(function(error){
return error;
})
};
this.addCategory = function(file, category){
console.log('category is ', category.dbName, 'file id is ', file._id);
return $http.put('/updateCategory', {
fileName: file.name,
categoryDbName: category.dbName,
fileId: file._id
})
.then(function(data){
if (data.status === 200){
return data;
} else {
return data;
}
}).catch(function(error){
return error;
})
};
this.isJsonString = function(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment