synt_backend
Version:
Synt light-weight node backend service
131 lines (120 loc) • 4.47 kB
JavaScript
var fs = require("fs");
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const { GetObjectCommand, S3Client } = require("@aws-sdk/client-s3");
const { Upload } = require("@aws-sdk/lib-storage");
// IAM USER:
// aws-sdk-image-uploads-user
// JS SDK v3 does not support global configuration.
// Codemod has attempted to pass values to each service client in this file.
// You may need to update clients outside of this file, if they use global config.
const getS3Client = () => {
return new S3Client({
region: process.env.AWS_REGION,
credentials: {
secretAccessKey: process.env.STORAGE_SECRET_ACCESS_KEY,
accessKeyId: process.env.STORAGE_ACCESS_KEY_ID,
},
});
};
export async function getPresignedUrl(file) {
if (file.bucket && file.key) {
try {
const client = new getS3Client();
const command = new GetObjectCommand({
Bucket: file.bucket,
Key: file.key,
ContentType: file.type,
});
const url = await getSignedUrl(client, command, {
expiresIn: 60 * 60 * 24 * 6.9,
});
return url;
} catch (error) {
console.error({ type: "getPresignedUrl Error", error });
}
}
return null;
}
export function uploadFileToBucket(file, folderPath = "") {
console.log("start uploading to s3");
// get file details
let { filepath, originalFilename, mimetype } = file;
// format name
const original_name = originalFilename;
const bucket_name = "synt-uploads";
// unique timestamp
let now = new Date();
let timestamp = now.getFullYear().toString(); // 2011
timestamp +=
(now.getMonth() < 9 ? "0" : "") + (now.getMonth() + 1).toString(); // JS months are 0-based, so +1 and pad with 0's
timestamp += (now.getDate() < 10 ? "0" : "") + now.getDate().toString(); // pad with a 0
timestamp += (now.getHours() < 10 ? "0" : "") + now.getHours().toString(); // pad with a 0
timestamp += (now.getMinutes() < 10 ? "0" : "") + now.getMinutes().toString(); // pad with a 0
timestamp += (now.getSeconds() < 10 ? "0" : "") + now.getSeconds().toString(); // pad with a 0
timestamp +=
(now.getMilliseconds < 10 ? "0" : "") + now.getMilliseconds().toString(); // pad with a 0
const name = timestamp + originalFilename;
// make sure slashes are correct
if (folderPath != "" && folderPath.slice(-1) != "/") folderPath += "/";
if (folderPath != "" && folderPath.charAt(0) === "/")
folderPath = folderPath.slice(1);
const key_name = `${folderPath}${name}`;
var fileStream = fs.createReadStream(filepath);
return new Promise((resolve, reject) => {
fileStream.on("open", async function () {
try {
let contentDeposition = 'inline;filename="' + name + '"';
// create s3 bucket params for upload
const params = {
Bucket: bucket_name,
Key: key_name,
ContentType: mimetype,
Body: fileStream,
ContentDisposition: contentDeposition,
};
console.log("create multipartUpload");
const multipartUpload = new Upload({
client: getS3Client(),
params,
});
console.log("new Upload");
multipartUpload.on("httpUploadProgress", (progress) => {
console.log(progress);
});
console.log("Start new Upload");
const response = await multipartUpload.done();
console.log({ type: "multipartUpload", response });
let File = {
bucket: bucket_name,
key: key_name,
type: mimetype,
url: response.Location,
original_name,
};
File.presignedUrl = await getPresignedUrl(File);
console.log({ type: "File", File });
resolve({ success: true, File });
} catch (error) {
// Use JSON.stringify with a replacer function to log nested errors
console.error(
"Upload failed: ",
JSON.stringify(error, Object.getOwnPropertyNames(error), 2)
);
if (error.errors) {
// If there is an 'errors' array, log each error in detail
error.errors.forEach((err, index) => {
console.error(
`Error #${index + 1}:`,
JSON.stringify(err, Object.getOwnPropertyNames(err), 2)
);
});
}
reject(error);
}
});
fileStream.on("error", function (err) {
console.log({ type: "fileStream Error", error });
reject(err);
});
});
}