skip to content
A cartoon cactus looking at the 'Astro.build' logo Max Campbell

How to upload files to S3 with Actix Web in Rust

Upload files to S3 in Actix Web with rust via Direct Uploading.

Recently I needed to upload files to S3 inside of actix web. And decided to use direct uploading for increased. If you don’t know when to upload files normally you have to send the file to your server and then the server sends that file to S3. But with direct uploading, the server generates a special signed URL for securely uploading files and the browser uploads it directly significantly increasing speed. Todo this we need to implement the s3 signed URL generator in actix web I used this code snippet to do this:

async fn generate_image_signed_url(req: HttpRequest) -> impl Responder {
    // Verify JWT
    verify_jwt(get_auth_token(&req).unwrap());
    // Pull creds
    let provider = ChainProvider::new();
    let credentials = provider.credentials().await.unwrap();

    let region = if let Ok(url) = std::env::var("AWS_ENDPOINT_URL") {
        Region::Custom {
            name: std::env::var("AWS_REGION").unwrap_or_else(|_| "custom".to_string()),
            endpoint: url,
        }
    } else {
        Region::default()
    };

    let options = PreSignedRequestOption {
        expires_in: std::time::Duration::from_secs(300),
    };
    let key = nanoid!(16);
    let req = PutObjectRequest {
        bucket: "homecooked-product-images".to_string(),
        key: key.clone() + ".jpeg",
        content_type: Some(String::from("image/jpeg")),
        ..Default::default()
    };
    let url = req.get_presigned_url(&region, &credentials, &options);
    let result = GenerateImageSignedUrlResult {
        url,
        key
    };

    return HttpResponse::Ok().json(result)
}

Conclusion

And then on the client, we can just PUT the image to this URL. And the file is uploaded!

Common Problems

error: SignatureDoesNotMatch If you are having this problem check: Make sure you are passing the correct Content Type Header. Check that you are using POST with the form upload method, or PUT with the transfer acceleration endpoint. The file type and file key MUST exactly match the one which was provided when the pre-signed URL was created. When using POST FormData method, check that you are sending all the form fields that were generated by AWS S3 SDK.