使用Streamlit上传文件至S3报错:filename must be a path 求助
问题:Streamlit上传文件到S3报错"filename must be a path"
我用Streamlit开发的应用要把文件上传到S3存储桶,但遇到错误:filename must be a path。发现Streamlit会临时存储上传的文件,但拿不到临时文件路径,打印也没结果;之前指定本地文件路径上传的代码是正常运行的。
原代码如下:
import streamlit as st import requests from dotenv import load_dotenv import boto3 from botocore.exceptions import NoCredentialsError, PartialCredentialsError,ClientError import io import os import time def upload_to_s3(file_path,bucket_name,object_name=None): s3=boto3.client("s3") if object_name is None: object_name=file_path try: s3.upload_file(file_path,bucket_name,object_name) except ClientError as e: print("Client error occured {e}") def main(): bucket="shellkode1111" st.set_page_config(page_title="apptech",layout="wide") st.title("Apple") uploaded_file=st.file_uploader("Upload file",type=["mp4"]) s3=boto3.client("s3") sts=boto3.client("sts") response = s3.head_bucket(Bucket="shellkode1111") try: s3.upload_file(uploaded_file,bucket,uploaded_file.name) except ClientError as e: print("Client Error occured {e}") print(response) bucket="shellkode1111" print("------------------------------") print(uploaded_file) print("----------------------------------") print("Working1") if(uploaded_file): print("Working") response=upload_to_s3(uploaded_file,bucket,uploaded_file) if __name__== "__main__": main()
问题原因
- Streamlit的
st.file_uploader()返回的是UploadedFile对象(类文件对象),并非本地文件路径字符串,而boto3的s3.upload_file()方法要求第一个参数必须是本地文件的路径,直接传入对象会触发路径错误。 - 原代码中调用
upload_to_s3时,第三个参数错误传入了uploaded_file对象,应该传入文件名或自定义的S3对象名。
解决方案
使用boto3的upload_fileobj()方法,该方法支持直接上传类文件对象,无需本地路径。修改后的代码如下:
import streamlit as st import boto3 from botocore.exceptions import NoCredentialsError, PartialCredentialsError, ClientError from dotenv import load_dotenv import os # 加载环境变量(确保AWS密钥配置正确) load_dotenv() def upload_to_s3(file_obj, bucket_name, object_name): s3 = boto3.client("s3") try: # 使用upload_fileobj上传类文件对象 s3.upload_fileobj(file_obj, bucket_name, object_name) return True except ClientError as e: print(f"客户端错误: {e}") return False except NoCredentialsError: print("未找到AWS凭证,请检查配置") return False except PartialCredentialsError: print("AWS凭证不完整,请检查配置") return False def main(): bucket = "shellkode1111" st.set_page_config(page_title="apptech", layout="wide") st.title("Apple") uploaded_file = st.file_uploader("Upload file", type=["mp4"]) # 验证桶是否存在(可选) s3 = boto3.client("s3") try: s3.head_bucket(Bucket=bucket) st.success(f"已连接到存储桶: {bucket}") except ClientError as e: st.error(f"无法连接到存储桶: {bucket},错误: {e}") return if uploaded_file: st.info(f"准备上传文件: {uploaded_file.name}") # 重置文件指针到开头(避免读取为空) uploaded_file.seek(0) # 调用上传函数,传入文件对象和文件名 if upload_to_s3(uploaded_file, bucket, uploaded_file.name): st.success(f"文件 {uploaded_file.name} 上传成功!") else: st.error("文件上传失败,请检查日志") if __name__ == "__main__": main()
关键修改点
- 替换
s3.upload_file()为s3.upload_fileobj(),直接接收Streamlit返回的UploadedFile对象 - 重构
upload_to_s3函数,参数改为文件对象和明确的S3对象名,移除错误的路径逻辑 - 添加
uploaded_file.seek(0)确保文件指针在开头,避免读取内容为空 - 完善异常捕获,区分凭证错误、客户端错误等场景,方便排查问题
- 用Streamlit的
st.success/st.error替代控制台打印,在页面展示状态反馈
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

