Skip to content

Instantly share code, notes, and snippets.

@namila007
Last active June 8, 2020 20:45
Show Gist options
  • Save namila007/2eb362a98f9a2530900a8c875eb534f2 to your computer and use it in GitHub Desktop.
Save namila007/2eb362a98f9a2530900a8c875eb534f2 to your computer and use it in GitHub Desktop.
aws-tutorial
const config = require("./config/config")
const express = require("express")
const bodyParser = require("body-parser")
const morgan = require('morgan')
const cors = require("cors")
const router = require("./router/router")
const helmet = require('helmet')
const app = express()
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json())
app.use(cors())
app.use(morgan('combined'))
app.use(helmet())
app.use("/api/",router)
app.listen(config.port,() => {
console.log(`${config.app} App run in PORT:${config.port}`)
})
const AWS = require('aws-sdk')
const config = require("../config/config")
AWS.config.update({
credentials: {
accessKeyId: config.aws.accessKeyId,
secretAccessKey: config.aws.secretAccessKey
},
region:config.aws.region
})
const s3 = new AWS.S3()
module.exports = s3
const getObjectList = (req, res, next) => {
let params = {
Bucket: config.aws.bucket, /* required */
Prefix: config.aws.basicPath,
MaxKeys: 10
}
if(req.query.ContinuationToken) params.ContinuationToken = decodeURI(req.query.ContinuationToken)
s3.listObjectsV2(params, (err, data) => {
if(err) {
next(err)
}
let response = {
IsTruncated: data.IsTruncated,
Contents: data.Contents
}
if(data.NextContinuationToken) response.NextContinuationToken = data.NextContinuationToken
if(data.ContinuationToken) response.ContinuationToken = data.ContinuationToken
res.status(httpStatus.OK).json(response)
})
}
const getObjectByKey = async (req, res, next) => {
let key = decodeURI(req.query.KEY)
// testing if the key contains basic
try {
if(!key) {
throw new Error("KEY REQUIRED")
}
if(!RegExp(`${config.aws.basicPath}/*`).test(key)) {
throw new Error("INVALID KEY "+ key)
}
let params = {
Bucket: config.aws.bucket,
Key: key,
Expires: expireTime
}
const signedUrl= await s3.getSignedUrlPromise('getObject', params)
let respond = {
key: key,
url: signedUrl,
expires: expireTime
}
res.status(httpStatus.ACCEPTED).json(respond)
}
catch (error){
next(error)
}
}
const putObject = async (req, res, next) => {
try {
const fileObject = req.body
if(!fileObject || !fileObject.hasOwnProperty('name') || !fileObject.hasOwnProperty('contentMD5') || !fileObject.hasOwnProperty('contentType'))
{
throw new Error ("Missing values in File Object \n"+fileObject)
}
const key = config.aws.basicPath +fileObject.name
let params = {
Bucket: config.aws.bucket,
Key: key,
ContentType: fileObject.contentType,
ContentMD5: fileObject.contentMD5,
ACL: "public-read",
Expires: expireTime
}
const signedUrl = await s3.getSignedUrlPromise('putObject', params)
let respond = {
key: key,
url: signedUrl,
expires: expireTime
}
res.status(httpStatus.OK).json(respond)
} catch(error) {
next(error)
}
}
const s3 = require("../services/awsS3")
const config = require("../config/config")
const httpStatus = require('http-status-codes');
const expireTime = 60 * 60 //1Hour
require('dotenv').config()
module.exports = {
port: process.env.SERVER_PORT,
app: process.env.APP,
env: process.env.NODE_ENV,
aws: {
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
bucket:process.env.AWS_BUCKET,
region:process.env.AWS_REGION,
basicPath: process.env.BASIC_UPLOAD_PATH
}
}
/**
*
* @param {*} downloadUrl pre-signed url
* @param {*} filePath saving path ie: abc/ab.jpg
*/
function downloadFiles (downloadUrl, filePath) {
console.log("Downloading Started")
return axios({
method: 'get',
url: downloadUrl,
responseType: 'stream'
})
.then(function (res) {
res.data.pipe(fs.createWriteStream(filePath))
console.log("Download Completed")
return true
})
.catch(e => {
handleErrors(e.response.data)
})
}
/**
*
* @param {*} key object key
*/
function getDownloadURLObject (key) {
let encodedKey = encodeURI(key)
return axios.get(`http://localhost:3030/api/item/?KEY=${encodedKey}`)
.then(respond => {
if (respond.status === 202) {
return respond.data
} else {
throw new Error(` Error Occured ${respond.data.error}`)
}
}).catch(e => {
handleErrors(e.response.data || e.message || e)
})
}
const axios = require("axios")
const fs = require("fs")
const path = require("path")
/**
*
* @param {*} key Object key
*/
async function handleDownload (key) {
try {
// Defining filename n path
let arr = key.split("/")
const fileName = arr[arr.length-1]
const savePath = path.join(__dirname,"..","downloads", fileName)
let signedDLObject = await getDownloadURLObject(key)
return Promise.resolve(downloadFiles(signedDLObject.url,savePath))
}
catch (error) {
return Promise.reject(error)
}
}
/**
*
* @param {*} downloadUrl pre-signed url
* @param {*} filePath saving path ie: abc/ab.jpg
*/
function downloadFiles (downloadUrl, filePath) {
console.log("Downloading Started")
return axios({
method: 'get',
url: downloadUrl,
responseType: 'stream'
})
.then(function (res) {
res.data.pipe(fs.createWriteStream(filePath))
console.log("Downloaded")
return true
})
.catch(e => {
handleErrors(e.response.data)
})
}
/**
*
* @param {*} key object key
*/
async function getDownloadURLObject (key) {
let encodedKey = encodeURI(key)
return axios.get(`http://localhost:3030/api/item/?KEY=${encodedKey}`)
.then(respond => {
if (respond.status === 202) {
return respond.data
} else {
throw new Error(` Error Occured ${respond.data}`)
}
}).catch(e => {
handleErrors(e.response.data)
})
}
/**
*
* @param {*} e error
*/
function handleErrors (e) {
throw new Error (e.message || e )
}
module.exports = {
handleDownload: handleDownload
}
const express = require('express')
const router = express.Router()
const awsController = require("../controllers/awsS3Controller")
router.get("/status", (req,res) => {
res.status(200).send({status:"OK"})
})
router.put("/upload", awsController.putObject)
router.get("/itemlist", awsController.getObjectList)
router.get("/item", awsController.getObjectByKey)
module.exports = router
async function getUploadURLObject (md5hash, fileName, contentType) {
let data = {
"name": fileName,
"contentType": contentType,
"contentMD5": md5hash
}
return axios.put("http://localhost:3030/api/upload", data)
.then(respond => {
if (respond.status === 200) {
return respond.data
} else {
throw new Error(`Error Occurred ${respond.data}`)
}
}).catch(e => {
handleErrors(e.response.data)
})
}
function uploadFile (filebuff, md5hash, uploadURL, contentType) {
console.log("Saving online")
return axios.put(uploadURL, filebuff,
{ headers: { "Content-MD5": md5hash , "Content-Type": contentType}})
.then(function (res) {
console.log("Saved online")
return res.status
})
.catch(e => {
handleErrors(e.response.data)
})
}
const axios = require("axios")
const fs = require("fs")
const path = require("path")
const crypto = require("crypto")
/**
*
* @param {*} filePath = saving path with file name
* @param {*} contentType = content type
*
*/
async function handleUpload (filePath, contentType) {
try {
const fileSystemPath = path.join(filePath)
const fileName = path.basename(fileSystemPath)
const filebuff = fileBuffer(fileSystemPath)
const md5hash = fileHash(filebuff)
const generatedUploadURL = await getUploadURLObject(md5hash, fileName, contentType)
const signedURL = generatedUploadURL.url
const res = uploadFile(filebuff, md5hash, signedURL, contentType)
return Promise.resolve(res)
}
catch (error) {
return Promise.reject(error)
}
}
/**
*
* @param {*} filebuff - file buffer
* @param {*} md5hash - raw md5 hash
* @param {*} uploadURL - presigned url
* @param {*} contentType
* {"Content-MD5": md5hash } header is required when uploading
*/
function uploadFile (filebuff, md5hash, uploadURL, contentType) {
console.log("Saving online")
return axios.put(uploadURL, filebuff,
{ headers: { "Content-MD5": md5hash , "Content-Type": contentType}})
.then(function (res) {
console.log("Saved online")
return res.status
})
.catch(e => {
handleErrors(e.response.data)
})
}
/**
*
* @param {*} md5hash
* @param {*} fileName
* @param {*} orderId
*/
async function getUploadURLObject (md5hash, fileName, contentType) {
let data = {
"name": fileName,
"contentType": contentType,
"contentMD5": md5hash
}
return axios.put("http://localhost:3030/api/upload", data)
.then(respond => {
if (respond.status === 200) {
return respond.data
} else {
throw new Error(`Error Occurred ${respond.data}`)
}
}).catch(e => {
handleErrors(e.response.data)
})
}
/**
*
* @param {*} file
*/
function fileBuffer (file) {
let data = fs.readFileSync(file)
return Buffer.from(data, "binary")
}
/**
*
* @param {*} filebuffer
* @returns {raw base64 value}
*/
function fileHash (filebuffer) {
return crypto.createHash("md5").update(filebuffer).digest("base64")
}
/**
*
* @param {*} e error
*/
function handleErrors (e) {
throw new Error (e.message || e )
}
module.exports = {
handleUpload: handleUpload,
fileHash: fileHash
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment