H
Hono•4d ago
Minh Techie

Image uploaded to S3 cannot be displayed when run on Lambda

I'm trying to upload images to S3 via AWS Lambda using Hono, but when I open the image url it shows The image cannot be displayed because it contains error My Setup: - Frontend: SvelteKit, sending a multipart/form-data request with the image. - Backend: AWS Lambda with Hono Here's my route
routes.put("/:channelId", async (c: Context) => {
const channelId = c.req.param("channelId");

const formData = await c.req.formData();

const updatedChannel = await ChannelService.updateChannel(
channelId,
formData
);

return c.json(updatedChannel, 200);
});
routes.put("/:channelId", async (c: Context) => {
const channelId = c.req.param("channelId");

const formData = await c.req.formData();

const updatedChannel = await ChannelService.updateChannel(
channelId,
formData
);

return c.json(updatedChannel, 200);
});
The code for the uploading part is in the comment. It works perfectly fine on my local machine but once run on Lambda, the image is corrupted for whatever reason
11 Replies
Minh Techie
Minh TechieOP•4d ago
ChannelService.updateChannel
async function updateChannel(channelId: string, formData: FormData) {
let profileImgUrl: string = "";
let bannerUrl: string = "";

const profileImg = formData.get("profile_img");

if (profileImg && typeof profileImg === "object" && "name" in profileImg) {
profileImgUrl = await S3Service.uploadFile(profileImg);
}

const bannerImg = formData.get("banner");

if (bannerImg && typeof bannerImg === "object" && "name" in bannerImg) {
bannerUrl = await S3Service.uploadFile(bannerImg);
}

// logic to update the channel info in the DB
return updatedChannel;
}
async function updateChannel(channelId: string, formData: FormData) {
let profileImgUrl: string = "";
let bannerUrl: string = "";

const profileImg = formData.get("profile_img");

if (profileImg && typeof profileImg === "object" && "name" in profileImg) {
profileImgUrl = await S3Service.uploadFile(profileImg);
}

const bannerImg = formData.get("banner");

if (bannerImg && typeof bannerImg === "object" && "name" in bannerImg) {
bannerUrl = await S3Service.uploadFile(bannerImg);
}

// logic to update the channel info in the DB
return updatedChannel;
}
S3Service
const S3Service = {
uploadFile: async (file: File) => {
if (!bucketName || !region) {
throw new Error("Missing required bucket name and region");
}

const fileId = v4();

const fileExtension = file.name.split(".").pop();
const fileKey = `${fileId}.${fileExtension}`;

const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

const params = {
Body: buffer,
Bucket: bucketName,
Key: fileKey,
ContentType: file.type,
};

const uploadCommand = new PutObjectCommand(params);
const response = await s3Client.send(uploadCommand);

if (!response) return "Failed to upload file";

const url = `https://${bucketName}.s3.${region}.amazonaws.com/${fileKey}`;
return url;
},
};
const S3Service = {
uploadFile: async (file: File) => {
if (!bucketName || !region) {
throw new Error("Missing required bucket name and region");
}

const fileId = v4();

const fileExtension = file.name.split(".").pop();
const fileKey = `${fileId}.${fileExtension}`;

const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);

const params = {
Body: buffer,
Bucket: bucketName,
Key: fileKey,
ContentType: file.type,
};

const uploadCommand = new PutObjectCommand(params);
const response = await s3Client.send(uploadCommand);

if (!response) return "Failed to upload file";

const url = `https://${bucketName}.s3.${region}.amazonaws.com/${fileKey}`;
return url;
},
};
ambergristle
ambergristle•4d ago
1. have you checked your S3? what's getting uploaded, or not? 2. have you confirmed that the file.type is being set correctly in deployment? you might also want to try using c.parseBody instead of c.formData parseBody actually works w multipart form data, and is the hono-recommended way to deal w file uploads: https://hono.dev/examples/file-upload while formData specifically returns a FormData instance
Minh Techie
Minh TechieOP•3d ago
@ambergristle 1. the image is uploaded successfully but when I view it it says The image cannot be displayed because contains error 2. yes it's correct. Here's what I see in CloudWatch
FormData {
banner: '',
profile_img: File {
size: 311948,
type: 'image/jpeg',
name: 'cat.jpg',
lastModified: 1737954587729
},
name: "My Channel",
description: 'This is My channel',
id: '...'
}
FormData {
banner: '',
profile_img: File {
size: 311948,
type: 'image/jpeg',
name: 'cat.jpg',
lastModified: 1737954587729
},
name: "My Channel",
description: 'This is My channel',
id: '...'
}
3. I tried c.parseBody but still no luck
ambergristle
ambergristle•3d ago
what's the logged content type of the files you're trying to upload?
Minh Techie
Minh TechieOP•3d ago
what do you mean? the type is jpeg
ambergristle
ambergristle•3d ago
ah, i see, you shared already: 'image/jpeg' huh do all the filenames have extensions?
Minh Techie
Minh TechieOP•3d ago
ambergristle
ambergristle•3d ago
sorry, it's been a minute since i used aws. i tried to avoid it i feel like in the past, i've needed to generate signed s3 urls. the s3 client has a method called getSignedUrl. maybe that would help?
Minh Techie
Minh TechieOP•3d ago
I have no idea 😅 I’ve tried Google, Gpt but nothing works. I guess I have to use something else
ambergristle
ambergristle•3d ago
oh, i meant to link this: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property i'd never discourage someone from ditching AWS, lol, but i hope signing helps
Minh Techie
Minh TechieOP•3d ago
Thanks! I will try this one

Did you find this page helpful?