Skip to content

Instantly share code, notes, and snippets.

@patheard
Last active September 8, 2022 03:23
Show Gist options
  • Save patheard/f75cdc16b0c45ce7c4863967b2fd7797 to your computer and use it in GitHub Desktop.
Save patheard/f75cdc16b0c45ce7c4863967b2fd7797 to your computer and use it in GitHub Desktop.
NextJS S3 object download API endpoint
import { NextApiRequest, NextApiResponse } from "next";
import { middleware } from "@lib/middleware";
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3";
import { logMessage } from "@lib/logger";
const FILE_ATTACHMENT_BUCKET = process.env.VAULT_FILE_STORAGE as string;
const s3Client = new S3Client({
endpoint: process.env.LOCAL_AWS_ENDPOINT ?? undefined,
forcePathStyle: process.env.LOCAL_AWS_ENDPOINT ? true : undefined,
region: process.env.AWS_REGION ?? "ca-central-1",
});
/**
* Download an S3 object with a give `key` query param
* @param req
* @param res
*/
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
let maxMemory = 0;
let previousUsed = getMemory();
const objectKey = req.query.key as string;
// Get the S3 object
const s3Object = await s3Client.send(
new GetObjectCommand({
Bucket: FILE_ATTACHMENT_BUCKET,
Key: objectKey,
})
);
// Stream the object back to the response
if (s3Object.Body) {
res.setHeader("Content-Type", "application/octet-stream");
res.setHeader("Content-Disposition", "attachment; filename=download.img");
const s3ObjectStream = s3Object.Body as NodeJS.ReadableStream;
s3ObjectStream
.on("data", () => {
const used = getMemory();
logMessage.info(`${objectKey}: streaming memory ${formatNumber(used)} MB (delta ${formatNumber(used - previousUsed)} MB)`);
maxMemory = Math.max(maxMemory, used);
previousUsed = used;
})
.on("end", () => {
logMessage.info(`${objectKey}: max memory ${formatNumber(maxMemory)} MB`);
});
s3ObjectStream.pipe(res);
}
};
const formatNumber = (num: number): string => {
return num.toLocaleString("en-CA");
}
const getMemory = (): number => {
return process.memoryUsage().heapUsed / 1024 / 1024;
}
export default middleware([], handler);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment