set up presigned urls api

This commit is contained in:
Khalim Conn-Kowlessar 2023-09-15 11:53:58 +01:00
parent 03e8ad00e6
commit fd7c1578ef
3 changed files with 72 additions and 37 deletions

View file

@ -0,0 +1,57 @@
import S3 from "aws-sdk/clients/s3";
import { NextRequest, NextResponse } from "next/server";
import { z } from "zod";
const presignedUrlSchema = z.object({
files: z.array(
z.object({
fileKey: z.string(),
contentType: z.string(),
})
),
});
export async function POST(request: NextRequest) {
const body = await request.json();
let validatedBody;
try {
validatedBody = presignedUrlSchema.parse(body);
} catch (error) {
console.error("Invalid input: ", error);
return new NextResponse(JSON.stringify({ msg: "Invalid input" }), {
status: 400,
});
}
try {
const s3 = new S3({
signatureVersion: "v4",
region: process.env.PRESIGN_AWS_REGION,
accessKeyId: process.env.PRSIGN_AWS_ACCESS_KEY,
secretAccessKey: process.env.PRESIGN_AWS_SECRET_KEY,
});
const { files } = validatedBody;
// generate a presigned URL for each file
const preSignedUrls = await Promise.all(
files.map(async (file: any) => {
return s3.getSignedUrlPromise("putObject", {
Bucket: process.env.RETOFIT_PLAN_INPUT_BUCKET_NAME,
Key: file.fileKey,
ContentType: file.contentType,
Expires: 5 * 60,
});
})
);
return new NextResponse(JSON.stringify({ url: preSignedUrls }), {
status: 200,
});
} catch (error) {
console.error(error);
return new NextResponse(JSON.stringify({ msg: "Internal server error" }), {
status: 500,
});
}
}

View file

@ -4,41 +4,14 @@ import { Input } from "@/app/shadcn_components/ui/input";
import { Label } from "@/app/shadcn_components/ui/label";
export function SelectFolder({
handleButtonDisabled,
setUploadMessage,
setFile,
handleOnChange,
}: {
handleButtonDisabled: (file?: File[]) => void;
setUploadMessage: (message: string) => void;
setFile: (file: File[]) => void;
handleOnChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}) {
function handleOnChange(e: React.ChangeEvent<HTMLInputElement>) {
if (e.target.files && e.target.files.length === 3) {
const files = Array.from(e.target.files);
const extensions = files.map((file) =>
file.name.split(".").pop()?.toLowerCase()
);
if (
extensions.includes("xml") &&
extensions.includes("pdf") &&
extensions.includes("docx")
) {
setFile(files); // You would need to update setFile to accept an array of files
handleButtonDisabled(files); // Similarly, update handleButtonDisabled to work with multiple files
} else {
setUploadMessage("Please select a .xml, .pdf, and .docx file.");
}
} else {
setUploadMessage("Please select exactly 3 files.");
}
}
return (
<Input
id="folder-uploader"
type="file"
// TODO: Handle accept - we want a folder
accept=".xml,.pdf,.docx"
multiple={true}
className="cursor-pointer"

View file

@ -5,13 +5,14 @@ import { SelectFolder } from "../components/due-considerations/SelectFolder";
import { Button } from "../shadcn_components/ui/button";
export default function DueConsiderationsHome() {
const [file, setFile] = useState<File[]>([]);
const [files, setFile] = useState<File[]>([]);
const [buttonDisabled, setButtonDisabled] = useState(true);
const [uploadMessage, setUploadMessage] = useState("");
function handleButtonDisabled(files?: File[]) {
if (files && files.length === 3) {
const extensions = files.map((file) =>
function handleOnChange(e: React.ChangeEvent<HTMLInputElement>) {
if (e.target.files && e.target.files.length === 3) {
const filesArray = Array.from(e.target.files);
const extensions = filesArray.map((file) =>
file.name.split(".").pop()?.toLowerCase()
);
@ -20,7 +21,9 @@ export default function DueConsiderationsHome() {
extensions.includes("pdf") &&
extensions.includes("docx")
) {
setFile(files);
setButtonDisabled(false);
setUploadMessage("");
} else {
setUploadMessage("Please select a .xml, .pdf, and .docx file.");
setButtonDisabled(true);
@ -31,6 +34,10 @@ export default function DueConsiderationsHome() {
}
}
function onUpload() {
// We want to upload the files to s3 via a presigned link
}
return (
<div className="flex flex-col items-center mt-20 tracking-wider leading-loose">
<div className="text-center">
@ -45,10 +52,7 @@ export default function DueConsiderationsHome() {
</div>
<div className="mb-5">
<SelectFolder
handleButtonDisabled={handleButtonDisabled}
setFile={setFile}
/>
<SelectFolder handleOnChange={handleOnChange} />
</div>
<div className="flex justify-between w-full">
@ -56,6 +60,7 @@ export default function DueConsiderationsHome() {
<Button
disabled={buttonDisabled}
className="bg-brandblue hover:bg-hoverblue"
onClick={onUpload}
>
Upload
</Button>