Skip to content

Commit

Permalink
adds pdf and csv
Browse files Browse the repository at this point in the history
  • Loading branch information
Billions94 committed Nov 15, 2021
1 parent 3af0818 commit 767b657
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 3 deletions.
93 changes: 91 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@
"author": "",
"license": "ISC",
"dependencies": {
"btoa": "^1.2.1",
"cloudinary": "^1.27.1",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-list-endpoints": "^6.0.0",
"express-validator": "^6.13.0",
"fs-extra": "^10.0.0",
"http-errors": "^1.8.0",
"json2csv": "^5.0.6",
"mongoose": "^6.0.12",
"multer": "^1.4.3",
"multer-storage-cloudinary": "^4.0.0",
"node-fetch": "^3.1.0",
"pdfmake": "^0.2.4",
"query-to-mongo": "^0.10.1"
},
Expand Down
28 changes: 27 additions & 1 deletion src/APIs/experience/e-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,33 @@ import ExperienceModel from './schema.js'
import UserModel from '../users/schema.js'
import q2m from 'query-to-mongo'
import createHttpError from 'http-errors'
import json2csv from 'json2csv'
import { pipeline } from 'stream'


// Create CSV for Experience
const createCSV = async (req, res, next) => {
try {
res.setHeader("Content-Disposition", "attachment; filename=experience.csv")

const id = req.params.id
const user = await UserModel.findById(id)
const exp = ExperienceModel.findById(id)

const source = exp

const transform = new json2csv.Transform({ fields: ["company"] })
const destination = res

pipeline(source, transform, destination, err => {
if (err) next(err)
})
} catch (error) {
console.error(error)
next(error)
}
}

// Create new Experience
const createExperience = async (req, res, next) => {
try {
Expand Down Expand Up @@ -98,7 +123,8 @@ const experienceHandler = {
getAllExperiences,
getExpByID,
updateExperience,
deleteExperience
deleteExperience,
createCSV
}

export default experienceHandler
1 change: 1 addition & 0 deletions src/APIs/experience/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const experienceRouter = express.Router()

experienceRouter.post('/:userId', experienceHandler.createExperience)

experienceRouter.get('/:id/downloadCSV', experienceHandler.createCSV)
experienceRouter.get('/', experienceHandler.getAllExperiences)

experienceRouter.route('/:id')
Expand Down
70 changes: 70 additions & 0 deletions src/APIs/pdf/pdfTools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import PdfPrinter from "pdfmake";
import btoa from "btoa";
import fetch from "node-fetch";
import { extname } from "path";


const fonts = {
Helvetica: {
normal: "Helvetica",
bold: "Helvetica-Bold",
italics: "Helvetica-Oblique",
bolditalics: "Helvetica-BoldOblique",
},
};

const printer = new PdfPrinter(fonts);

const fetchIamgeBuffer = async (image) => {
let result = await fetch(image, {
responseType: "arraybuffer",
});
return result.arrayBuffer();
};

export const getPDFReadableStream = async (data) => {
let imagePath = {};
if (data.image) {
let imageBufferArray = await fetchIamgeBuffer(data.image);
console.log(imageBufferArray);

const base64String = btoa(
String.fromCharCode(...new Uint8Array(imageBufferArray))
);
console.log(base64String);

const imageUrlPath = data.image.split("/");
const fileName = imageUrlPath[imageUrlPath.length - 1];
const extension = extname(fileName);
const base64Pdf = `data:image/${extension};base64,${base64String}`;

imagePath = { image: base64Pdf, width: 500, margin: [0, 0, 0, 40] };
}

const docDefinition = {
content: [
imagePath,
{ text: data.name, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.surname, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.email, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.userName, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.job, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.bio, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
{ text: data.area, fontSize: 20, bold: true, margin: [0, 0, 0, 40] },
],
defaultStyle: {
font: "Helvetica",
},
};

const options = {};

const pdfReadableStream = printer.createPdfKitDocument(
docDefinition,
options
);
// pdfReadableStream.pipe(fs.createWriteStream('document.pdf')); // old syntax for piping
// pipeline(pdfReadableStream, fs.createWriteStream('document.pdf')) // new syntax for piping (we don't want to pipe pdf into file on disk right now)
pdfReadableStream.end();
return pdfReadableStream;
};
40 changes: 40 additions & 0 deletions src/APIs/users/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,52 @@
import express from 'express';
import usersHandler from './u-handler.js'
import { usersValidator } from './validator.js';
import UserModel from './schema.js'
import { getPDFReadableStream } from '../pdf/pdfTools.js';
import { pipeline } from "stream";
import { CloudinaryStorage } from 'multer-storage-cloudinary';
import { v2 as cloudinary } from 'cloudinary'
import multer from 'multer'

const usersRouter = express.Router()

// IMAGE CLOUD STORAGE
const cloudinaryStorage = new CloudinaryStorage({
cloudinary, // CREDENTIALS,
params: {
folder: "linkedIN-BE",
},
});

usersRouter.get('/', usersHandler.getAllUsers)
usersRouter.post('/', usersValidator, usersHandler.createUser)

usersRouter.put('/:id/upload', multer({ storage: cloudinaryStorage}).single('image'), usersHandler.postPicture)

usersRouter.get('/:id/CV', async (req, res, next) =>{
try {
const id = req.params.id
const data = await UserModel.findById(id)

if(!data){
res
.status(404)
.send({ message: `data with id ${id} is not found!` });
} else {
res.setHeader("Content-Disposition", `attachment; filename=${data.id}.pdf`)

const source = await getPDFReadableStream(data)
const destination = res

pipeline(source, destination, err => {
if (err) next(err)
})
}
} catch (error) {
next(error)
}
})

usersRouter.route('/:id')
.get(usersHandler.getUserById)
.put(usersHandler.updateUser)
Expand Down
1 change: 1 addition & 0 deletions src/APIs/users/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const UserSchema = new Schema(
job: { type: String, required: true },
bio: { type: String, required: true },
area: { type: String, required: true },
experiences: [ { type: Schema.Types.ObjectId, ref: 'Experience'}]
},
{
timestamps: true
Expand Down
Loading

0 comments on commit 767b657

Please sign in to comment.