Cannot upload streamlit Uploaded.file to s3 Bucket

I have built a streamlit app that has PDF file input. It works fine, the results are later saved to MySQL server, but I want to save the initial pdf to s3 bucket for later checks and keep getting errors no matter what I do.

Here is the relevant code:

pdf = st.file_uploader(label='Drag the PDF file here. Limit 100MB')
if pdf is not None:

bluh bluh and in the end:

s3 = boto3.resource(
        service_name='s3',
        region_name='xxx',
        aws_access_key_id='xxx',
        aws_secret_access_key='xxx',
    )

    bucket_name = 'xxx'
    print(pdf)
    print(type(pdf))
    pdf.seek(0)
    name = 'pdf_' + str(id) + '.pdf'
    print(name)
    s3.Bucket(bucket_name).upload_fileobj(pdf, 'pdf_storage', name)

error I get:

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 563, in _run_script
    exec(code, module.__dict__)
  File "/app/main.py", line 124, in <module>
    s3.Bucket(bucket_name).upload_fileobj(pdf, 'pdf_storage', name)
  File "/usr/local/lib/python3.9/site-packages/boto3/s3/inject.py", line 678, in bucket_upload_fileobj
    return self.meta.client.upload_fileobj(
  File "/usr/local/lib/python3.9/site-packages/boto3/s3/inject.py", line 629, in upload_fileobj
    future = manager.upload(
  File "/usr/local/lib/python3.9/site-packages/s3transfer/manager.py", line 321, in upload
    self._validate_all_known_args(extra_args, self.ALLOWED_UPLOAD_ARGS)
  File "/usr/local/lib/python3.9/site-packages/s3transfer/manager.py", line 500, in _validate_all_known_args
    raise ValueError(
ValueError: Invalid extra_args key 'p', must be one of: ACL, CacheControl, ChecksumAlgorithm, ContentDisposition, ContentEncoding, ContentLanguage, ContentType, ExpectedBucketOwner, Expires, GrantFullControl, GrantRead, GrantReadACP, GrantWriteACP, Metadata, ObjectLockLegalHoldStatus, ObjectLockMode, ObjectLockRetainUntilDate, RequestPayer, ServerSideEncryption, StorageClass, SSECustomerAlgorithm, SSECustomerKey, SSECustomerKeyMD5, SSEKMSKeyId, SSEKMSEncryptionContext, Tagging, WebsiteRedirectLocation

If you use boto3.client instead of resource, and s3.upload_fileobj instead of s3.Bucket.upload_fileobj, it should work.

import boto3
import streamlit as st

pdf = st.file_uploader(label="Drag the PDF file here. Limit 100MB")
if pdf is not None:
    s3 = boto3.client(
        service_name="s3",
        region_name="xxx",
        aws_access_key_id="xxx",
        aws_secret_access_key="xxx",
    )

    id = 123
    bucket_name = "xxx"
    print(pdf)
    print(type(pdf))
    pdf.seek(0)
    name = "pdf_" + str(id) + ".pdf"
    print(name)
    s3.upload_fileobj(pdf, "pdf_storage", name)
1 Like