upload works

This commit is contained in:
Jun-te kim 2025-08-12 19:28:40 +00:00
parent da8500c01b
commit c7b9d6de9d
5 changed files with 165 additions and 19 deletions

108
.env.development Normal file
View file

@ -0,0 +1,108 @@
NEXTAUTH_SECRET=df425f28-06ab-47c2-bb78-7e604387d463
NEXTAUTH_URL=http://localhost:3000
GOOGLE_CLIENT_ID=232063354367-ustovlgtk3cmtvohvd6tdlejnj1qjjj0.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=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
EPC_AUTH_TOKEN=a2Nvbm5rb3dsZXNzYXJAZ21haWwuY29tOjY5MGJiMWM0NmIyOGI5ZDUxYzAxMzQzYzNiZGNlZGJjZDNmODQwMzA=
AZURE_AD_B2C_TENANT_NAME=DomnaApp
AZURE_AD_B2C_CLIENT_ID=f0a1f977-ddc4-4037-b129-a310008ee934
AZURE_AD_B2C_CLIENT_SECRET=6uh8Q~dmZNqQy3ZxM_Ce33fVSeW24K27R~pYYduD
AZURE_AD_B2C_PRIMARY_USER_FLOW=B2C_1_signupsignin
AZURE_AD_CLIENT_ID=069e75ee-ba54-45ff-ba77-a06f29c0e21c
AZURE_AD_CLIENT_SECRET=x6D8Q~f2roqrnoP1YuomSGN5CvU0HPtIWqqPPaYW
AZURE_AD_TENANT_ID=4a85e8bb-8b7f-4bbd-adc2-1448bb6a9810
DB_HOST=terraform-20230705170609686900000001.cdgzupxvdyp0.eu-west-2.rds.amazonaws.com
DB_PORT=5432
DB_NAME=DevAssessmentModelDB
DB_USERNAME=DevAddessmentModelDB
DB_PASSWORD=!}-A=3D%(2Awy[Qx
URL=http://localhost:3000
PRESIGN_AWS_ACCESS_KEY=AKIAU5A36PPNMR2G7ZQO
PRESIGN_AWS_SECRET_KEY=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
RETROFIT_PLAN_INPUT_BUCKET_NAME=retrofit-plan-inputs-dev
PRESIGN_AWS_REGION=eu-west-2
DUE_CONSIDERATIONS_BUCKET=retrofit-due-considerations-dev
DUE_CONSIDERATIONS_AWS_ACCESS_KEY=AKIAU5A36PPNPNFWLJOY
DUE_CONSIDERATIONS_AWS_SECRET_KEY=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
DUE_CONSIDERATIONS_AWS_REGION=eu-west-2
ECO_SPREADSHEET_BUCKET=retrofit-eco-spreadsheet-dev
ECO_SPREADSHEET_AWS_ACCESS_KEY=AKIAU5A36PPNPTFDQGOJ
ECO_SPREADSHEET_AWS_SECRET_KEY=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
ECO_SPREADSHEET_AWS_REGION=eu-west-2
RETROFIT_ENERGY_ASSESSMENTS_BUCKET=retrofit-energy-assessments-dev
RETROFIT_ENERGY_ASSESSMENTS_AWS_ACCESS_KEY=AKIAU5A36PPNJMZZ3KRW
RETROFIT_ENERGY_ASSESSMENTS_AWS_SECRET=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
FASTAPI_API_KEY=4QPwbB6hEdUloDVtbBJCUTfGBdBgWwpeavWQ7t5Z
FASTAPI_API_URL=https://api.dev.hestia.homes
DUE_CONSIDERATIONS_API_URL=https://api.dev.hestia.homes
ECO_SPREADSHEET_API_URL=https://api.dev.hestia.homes
DOCUMENTS_DATABASE_URL=postgresql://postgres:makingwarmhomes@terraform-20250331175522503500000002.cdgzupxvdyp0.eu-west-2.rds.amazonaws.com:5432/surveyDB
DOCUMENTS_DB_HOST=terraform-20250331175522503500000002.cdgzupxvdyp0.eu-west-2.rds.amazonaws.com
DOCUMENTS_DB_PORT=5432
DOCUMENTS_DB_NAME=surveyDB
DOCUMENTS_DB_USERNAME=postgres
DOCUMENTS_DB_PASSWORD=makingwarmhomes

View file

@ -35,7 +35,7 @@ export async function POST(request: NextRequest) {
// Presigned url is valid for 5 minutes
const preSignedUrl = await s3.getSignedUrl("putObject", {
Bucket: process.env.RETOFIT_PLAN_INPUT_BUCKET_NAME,
Bucket: process.env.RETROFIT_PLAN_INPUT_BUCKET_NAME,
Key: fileKey,
ContentType: "text/csv",
Expires: 5 * 60,

View file

@ -5,18 +5,18 @@ import { createS3Client, presignGetUrl } from "@/app/utils/s3";
const Schema = z.object({
path: z.string(),
expiresInSeconds: z.number().int().positive().default(300),
responseContentType: z.string().optional(),
responseContentDisposition: z.string().optional(), // e.g., 'attachment; filename="file.csv"'
contentType: z.string(),
});
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { path, expiresInSeconds, responseContentType, responseContentDisposition } =
const { path, expiresInSeconds, contentType } =
Schema.parse(body);
// Retrofit s3 bucket connection
let bucket = process.env.RETROFIT_ENERGY_ASSESSMENTS_BUCKET
// let bucket = process.env.RETROFIT_PLAN_INPUT_BUCKET_NAME
if (!bucket) {
return NextResponse.json({ msg: "RETROFIT_ENERGY_ASSESSMENTS_BUCKET is not set" }, { status: 400 });
}
@ -24,15 +24,16 @@ export async function POST(request: NextRequest) {
const s3 = createS3Client({
region: process.env.PRESIGN_AWS_REGION,
accessKeyId: process.env.RETROFIT_ENERGY_ASSESSMENTS_AWS_ACCESS_KEY,
secretAccessKey: process.env.RETROFIT_ENERGY_ASSESSMENTS_AWS_ACCESS_KEY,
secretAccessKey: process.env.RETROFIT_ENERGY_ASSESSMENTS_AWS_SECRET,
});
const url = await presignGetUrl(s3, {
bucket,
key: path,
expiresInSeconds,
responseContentType,
responseContentDisposition,
ContentType: contentType,
});
return NextResponse.json({ url });
@ -42,4 +43,6 @@ export async function POST(request: NextRequest) {
? NextResponse.json({ msg: "Invalid input", issues: err.issues }, { status: 400 })
: NextResponse.json({ msg: "Internal server error" }, { status: 500 });
}
}
}

View file

@ -12,6 +12,7 @@ import { Button } from "@/app/shadcn_components/ui/button";
import { ReportType } from "@/app/db/documents_schema/documents";
import { Input } from "@/app/shadcn_components/ui/input";
import { useState } from "react";
import { uploadFileToS3 } from "@/app/utils/s3";
type UploadModalProps = {
open: boolean;
@ -35,11 +36,12 @@ async function generatePresignedUrls({
}) {
const body = JSON.stringify({
path: path,
responseContentType: contentType,
expiresInSeconds: expiresInSeconds
expiresInSeconds: expiresInSeconds,
contentType: contentType
});
const presignedResponse = await fetch("/api/upload/retrofit-energy-assessments-dev", {
const presignedResponse = await fetch("/api/upload/retrofit-energy-assessments", {
method: "POST",
headers: { "Content-Type": "application/json" },
body,
});
@ -61,13 +63,19 @@ export const UploadModal = ({
async function handleS3Upload() {
console.log("Get Presigned url in a specific bucket location")
console.log("files are", uploadFiles[0]);
const { url } = await generatePresignedUrls({
path: "foo/test/trololol", // path in bucket
contentType: "application/pdf",
expiresInSeconds: 5 * 60,
});
console.log("URl is ", url);
console.log("uploading file");
await uploadFileToS3({
presignedUrl: url,
file: uploadFiles[0],
contentType: "application/pdf"
})
onClose(); //probably khalim call back to update the front end properl
}

View file

@ -26,20 +26,47 @@ export type PresignGetOptions = {
bucket: string;
key: string;
expiresInSeconds?: number; // default 300
responseContentType?: string;
responseContentDisposition?: string; // e.g. 'attachment; filename="file.csv"'
ContentType?: string;
};
/** Presign a GET URL using an existing S3 instance (aws-sdk v2). */
export async function presignGetUrl(
s3: S3,
{ bucket, key, expiresInSeconds = 300, responseContentType, responseContentDisposition }: PresignGetOptions
{ bucket, key, expiresInSeconds = 300, ContentType}: PresignGetOptions
): Promise<string> {
return (s3 as any).getSignedUrlPromise("getObject", {
return (s3 as any).getSignedUrlPromise("putObject", {
Bucket: bucket,
Key: key,
Expires: expiresInSeconds,
ResponseContentType: responseContentType,
ResponseContentDisposition: responseContentDisposition,
ContentType: ContentType,
});
}
export async function uploadFileToS3({
presignedUrl,
file,
contentType,
}: {
presignedUrl: string;
file: Blob;
contentType: string;
}) {
try {
const response = await fetch(presignedUrl, {
method: "PUT",
body: file,
headers: { "Content-Type": contentType },
});
if (!response.ok) {
console.error("Upload failed response:", response);
throw new Error("Network response was not ok");
}
} catch (error) {
console.error("Upload error:", error);
throw new Error("Upload failed.");
}
console.log("File uploaded successfully");
return { success: true };
}