Skip to content

Commit

Permalink
[editor] Handle Uploading Attachments to Public S3 Bucket
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Holinshead committed Jan 9, 2024
1 parent bcd2921 commit c41575c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,66 @@ import {
} from "../../../../utils/dropzoneHelpers";
import { ActionIcon, Container, Text, Title, Tooltip } from "@mantine/core";
import { IconX } from "@tabler/icons-react";
import { ufetch } from "ufetch";
import { ROUTE_TABLE } from "../../../../utils/api";

type Props = {
schema: PromptInputObjectAttachmentsSchema;
onUploadAttachments: (attachments: InputAttachment[]) => void;
onCancel?: () => void;
};

async function uploadFile(_file: File) {
// TODO: Implement
return {
url: "https://s3.amazonaws.com/files.uploads.lastmileai.com/uploads/cldxsqbel0000qs8owp8mkd0z/2023_12_1_21_23_24/942/Screenshot 2023-11-28 at 11.11.25 AM.png",
};
// s3 file uris cannot have '+' character, so replace with '_'
function sanitizeFileName(name: string) {
return name.replace(/[_+]/g, "_");
}

export function getTodayDateString(): string {
const date = new Date();
const dateString = `${date.getFullYear()}_${
date.getMonth() + 1
}_${date.getDate()}`;
const timeString = `${date.getUTCHours()}_${date.getUTCMinutes()}_${date.getUTCSeconds()}`;
return `${dateString}_${timeString}`;
}

// TODO: Make this configurable for external deployments
async function uploadFile(file: File): Promise<{ url: string }> {
const randomPath = Math.round(Math.random() * 10000);
const policy = await ufetch.get(ROUTE_TABLE.UPLOAD_POLICY);
const uploadUrl = "https://s3.amazonaws.com/lastmileai.aiconfig.public/";
const uploadKey = `uploads/${getTodayDateString()}/${randomPath}/${sanitizeFileName(
file.name
)}`;

const formData = new FormData();
formData.append("key", uploadKey);
formData.append("acl", "public-read");
formData.append("Content-Type", file.type);
formData.append("AWSAccessKeyId", policy.AWSAccessKeyId);
formData.append("success_action_status", "201");
formData.append("Policy", policy.s3Policy);
formData.append("Signature", policy.s3Signature);
formData.append("file", file);

// See this about changing to use XMLHTTPRequest to show upload progress as well
// https://medium.com/@cpatarun/tracking-file-upload-progress-to-amazon-s3-from-the-browser-71be6712c63d
const rawRes = await fetch(uploadUrl, {
method: "POST",
mode: "cors",
cache: "no-cache",
body: formData,
headers: {
Authorization: "",
},
});

if (rawRes.ok && rawRes.status === 201) {
// Dont really need to parse xml s3 response, just use the keys, etc. that were passed
return { url: `${uploadUrl}${uploadKey}` };
} else {
throw new Error("Error uploading to S3!");
}
}

function getSupportedFileTypes(schema: PromptInputObjectAttachmentsSchema) {
Expand Down Expand Up @@ -66,7 +114,7 @@ Props) {
const attachments: Attachment[] = uploads.map((upload) => {
return {
data: upload.url,
mimeType: upload.mimeType,
mime_type: upload.mimeType,
};
});

Expand Down
1 change: 1 addition & 0 deletions python/src/aiconfig/editor/client/src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ export const ROUTE_TABLE = {
RUN_PROMPT: urlJoin(API_ENDPOINT, "/run"),
UPDATE_MODEL: urlJoin(API_ENDPOINT, "/update_model"),
UPDATE_PROMPT: urlJoin(API_ENDPOINT, "/update_prompt"),
UPLOAD_POLICY: "https://lastmileai.dev/api/upload/publicpolicy",
};

0 comments on commit c41575c

Please sign in to comment.