UNPKG

synt_backend

Version:

Synt light-weight node backend service

131 lines (120 loc) 4.47 kB
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); }); }); }