I am trying to upload an image to my s3 bucket but It does not seem to work for images over 1mb - seems to work fine for images under (even multiple ones) I am using Remix. Have no idea what it is not allowing large images?
// app/routes/test-upload.js
import { json } from "@remix-run/node";
import {
unstable_createMemoryUploadHandler,
unstable_parseMultipartFormData,
type ActionFunctionArgs,
type UploadHandler
} from "@remix-run/node";
import AWS from 'aws-sdk';
import { createId as cuid } from '@paralleldrive/cuid2';
// Simple logging for Tigris issue reproduction
function log(message) {
console.log(`[${new Date().toISOString()}] ${message}`);
}
// Configure AWS SDK with timeout settings
AWS.config.update({
httpOptions: {
timeout: 60000, // 1 minute timeout
connectTimeout: 10000 // 10 seconds connect timeout
},
maxRetries: 3
});
export async function action({ request }: ActionFunctionArgs) {
log("Starting upload to Tigris");
// Set up memory upload handler
const uploadHandler: UploadHandler = unstable_createMemoryUploadHandler({
maxPartSize: 10 * 1024 * 1024, // 10MB limit
});
try {
// Parse the form data
log("Parsing form data");
const formData = await unstable_parseMultipartFormData(request, uploadHandler);
// Get uploaded files
const files = formData.getAll("photoFiles") as File[];
log(`Found ${files.length} files`);
if (files.length === 0 || !(files[0] instanceof File)) {
return json({
success: false,
error: "No valid files found"
}, { status: 400 });
}
// Log file details for reference
files.forEach(file => {
log(`File: ${file.name}, Size: ${file.size} bytes, Type: ${file.type}`);
});
// Initialize S3 client
log("Setting up S3 client for Tigris");
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
endpoint: process.env.AWS_ENDPOINT_URL_S3 || "https://fly.storage.tigris.dev",
s3ForcePathStyle: true,
signatureVersion: "v4",
region: process.env.AWS_REGION || "auto"
});
// Test connection (minimal check)
try {
log("Testing S3 connection to Tigris");
await s3.headBucket({ Bucket: "ouichef-images" }).promise();
log("Connection test successful");
} catch (error) {
log(`Connection test failed: ${error.message}`);
return json({
success: false,
error: "Could not connect to Tigris S3"
}, { status: 500 });
}
// Process files
const uploadResults = [];
for (const file of files) {
const fileExtension = file.name.split('.').pop() || 'jpg';
const uniqueId = cuid();
const key = `test-images/${uniqueId}.${fileExtension}`;
const bucket = "ouichef-images";
try {
// Simple upload approach with timing information
log(`Uploading ${file.name} (${file.size} bytes) to ${key}`);
const startTime = Date.now();
// Convert to buffer
log("Converting file to buffer");
const arrayBuffer = await file.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
log(`Buffer created (${buffer.length} bytes)`);
// Upload to S3
log("Starting upload to Tigris");
const uploadResult = await s3.upload({
Bucket: bucket,
Key: key,
Body: buffer,
ContentType: file.type || 'application/octet-stream'
}).promise();
const endTime = Date.now();
log(`Upload completed in ${endTime - startTime}ms`);
uploadResults.push({
originalFilename: file.name,
location: uploadResult.Location,
key: uploadResult.Key,
bucket: uploadResult.Bucket,
size: file.size,
uploadTimeMs: endTime - startTime
});
} catch (error) {
}
}
// Return results
const successCount = uploadResults.filter(result => !result.error).length;
log(`Upload process complete: ${successCount}/${files.length} successful`);
return json({
success: successCount > 0,
message: `${successCount} of ${files.length} files uploaded`,
files: uploadResults
});
} catch (error) {
log(`General error: ${error.message}`);
return json({
success: false,
error: `Upload process failed: ${error.message}`
}, { status: 500 });
}
}
// Minimal UI for testing
export default function TestUpload() {
return (
<div style={{ maxWidth: "600px", margin: "0 auto", padding: "20px" }}>
<h1 style={{ marginBottom: "20px" }}>Tigris S3 Upload Test</h1>
<form method="post" encType="multipart/form-data">
<div style={{ marginBottom: "20px" }}>
<label htmlFor="photoFiles" style={{ display: "block", marginBottom: "5px" }}>
Select images:
</label>
<input
type="file"
id="photoFiles"
name="photoFiles"
accept="image/*"
multiple
style={{ width: "100%" }}
/>
</div>
<button
type="submit"
style={{
padding: "8px 16px",
backgroundColor: "#0070f3",
color: "white",
border: "none",
borderRadius: "4px",
cursor: "pointer"
}}
>
Upload to Tigris
</button>
</form>
<div style={{ marginTop: "20px", padding: "15px", backgroundColor: "#f5f5f5", borderRadius: "4px" }}>
<p>This is a minimal test case for Tigris S3 upload issues.</p>
<p>Check server logs for detailed diagnostic information.</p>
</div>
</div>
);
}
It tends to just time out - here is what i get when i upload images over 1mb
f you still wish to intercept this unhandled request, please create a request handler for it.
Read more: https://mswjs.io/docs/getting-started/mocks
[2025-04-29T13:15:31.198Z] Connection test successful
[2025-04-29T13:15:31.198Z] Uploading IMG_2298.jpeg (3605199 bytes) to test-images/ifw90jxqccobd5eppjcrwyae.jpeg
[2025-04-29T13:15:31.198Z] Converting file to buffer
[2025-04-29T13:15:31.199Z] Buffer created (3605199 bytes)
[2025-04-29T13:15:31.199Z] Starting upload to Tigris
whereas for smaller images it is fine ?
ead more: https://mswjs.io/docs/getting-started/mocks
[2025-04-29T13:15:19.106Z] Upload completed in 330ms
[2025-04-29T13:15:19.106Z] Upload process complete: 2/2 successful
Does anyone have any idea why this might be happening?