diff --git a/api.planx.uk/modules/file/service/uploadFile.ts b/api.planx.uk/modules/file/service/uploadFile.ts index a6ee74227b..ead3cee9af 100644 --- a/api.planx.uk/modules/file/service/uploadFile.ts +++ b/api.planx.uk/modules/file/service/uploadFile.ts @@ -79,9 +79,9 @@ export function generateFileParams( ACL: "public-read", Bucket: process.env.AWS_S3_BUCKET, Key: key, - Body: file.buffer || JSON.stringify(file), + Body: file.buffer, ContentDisposition: `inline;filename="${filename}"`, - ContentType: file.mimetype || "application/json", + ContentType: file.mimetype, }; return { diff --git a/api.planx.uk/modules/file/service/utils.ts b/api.planx.uk/modules/file/service/utils.ts index 0f95e170e5..85e58cd110 100644 --- a/api.planx.uk/modules/file/service/utils.ts +++ b/api.planx.uk/modules/file/service/utils.ts @@ -1,5 +1,6 @@ import { S3 } from "@aws-sdk/client-s3"; import { isLiveEnv } from "../../../helpers.js"; +import { Readable } from "stream"; export function s3Factory() { return new S3({ @@ -40,3 +41,23 @@ export function getS3KeyFromURL(fileURL: string): string { const key = [folder, file].map(decodeURIComponent).join("/"); return key; } + +export const convertObjectToMulterJSONFile = ( + data: Record, + fileName: string, +): Express.Multer.File => { + const buffer = Buffer.from(JSON.stringify(data)); + + return { + buffer: buffer, + originalname: fileName, + mimetype: "application/json", + size: buffer.length, + fieldname: "file", + encoding: "7bit", + stream: Readable.from(buffer), + destination: "", + filename: "", + path: "", + }; +}; diff --git a/api.planx.uk/modules/send/s3/index.ts b/api.planx.uk/modules/send/s3/index.ts index 6f7186ae8b..2a414d4e94 100644 --- a/api.planx.uk/modules/send/s3/index.ts +++ b/api.planx.uk/modules/send/s3/index.ts @@ -8,6 +8,7 @@ import { uploadPrivateFile } from "../../file/service/uploadFile.js"; import { markSessionAsSubmitted } from "../../saveAndReturn/service/utils.js"; import { isApplicationTypeSupported } from "../utils/helpers.js"; import type { SendIntegrationController } from "../types.js"; +import { convertObjectToMulterJSONFile } from "../../file/service/utils.js"; interface CreateS3Application { insertS3Application: { @@ -44,16 +45,16 @@ const sendToS3: SendIntegrationController = async (_req, res, next) => { const flowName = session?.flow?.name; // Generate the ODP Schema JSON, skipping validation if not a supported application type - const doValidation = isApplicationTypeSupported(passport); - const exportData = doValidation - ? await $api.export.digitalPlanningDataPayload(sessionId) - : await $api.export.digitalPlanningDataPayload(sessionId, true); + const skipValidation = !isApplicationTypeSupported(passport); + const exportData = await $api.export.digitalPlanningDataPayload( + sessionId, + skipValidation, + ); // Create and upload the data as an S3 file - const { fileUrl } = await uploadPrivateFile( - exportData, - `${sessionId}.json`, - ); + const filename = `${sessionId}.json`; + const file = convertObjectToMulterJSONFile(exportData, filename); + const { fileUrl } = await uploadPrivateFile(file, filename); // Send a notification with the file URL to the Power Automate webhook const webhookRequest: AxiosRequestConfig = { @@ -69,7 +70,7 @@ const sendToS3: SendIntegrationController = async (_req, res, next) => { service: flowName, environment: env, file: fileUrl, - payload: doValidation ? "Validated ODP Schema" : "Discretionary", + payload: skipValidation ? "Discretionary" : "Validated ODP Schema", }, }; const webhookResponse = await axios(webhookRequest) @@ -125,7 +126,7 @@ const sendToS3: SendIntegrationController = async (_req, res, next) => { res.status(200).send({ message: `Successfully uploaded submission to S3: ${fileUrl}`, - payload: doValidation ? "Validated ODP Schema" : "Discretionary", + payload: skipValidation ? "Discretionary" : "Validated ODP Schema", webhookResponse: webhookResponse.axiosResponse.status, auditEntryId: webhookResponse.id, });