将HTML保存到内存并上传至AWS S3,使用Python Boto3。

5
import boto3
from io import StringIO
s3 = boto3.client('s3')

display = # Altair Charting

buff = StringIO(display.save(str_obj, 'html'))

s3.upload_fileobj(buff.read(), BUCKET, 'index.html')

我认为如果提供完整的示例,会使问题更加复杂,因此我将Altair图表保留为注释。

无论如何,我尝试了大量将对象和文件保存到AWS S3存储桶的建议,但是我还没有理解。

保存到磁盘很简单:

display.save('index.html')

将此内容上传到S3相比之下似乎非常困难。我不确定我在哪里出了问题。也许upload_fileobj 不是正确的方法,但我已经尝试了多次,仍然无法使其正常工作。
使用此方法时,特定错误为ValueError: Fileobj必须实现read 更新:
buff = StringIO(display.save('str.html'))

s3.put_object(
   Bucket=BUCKET, 
   Key=f'{DASHBOARD}{mkt_type}/{symbol}/index.html',
   Body=buff.read()
   )

我的Bucket中的index.html文件大小为0字节。

更新2:

str_obj = StringIO()
display.save(str_obj, 'html')
buff = str_obj.read()

s3.put_object(
    Bucket=BUCKET, 
    Key=f'{DASHBOARD}{mkt_type}/{symbol}/index.html',
    Body=buff
    )

这也不行。我简直无法相信将文件保存到S3会这么复杂。回想一下:我没有getvalue()方法所需的buff

解决方案: 这不是我第一次与S3文件纠缠,所以我可能会为自己留下此信息以备将来参考。 话虽如此,我仍然不清楚为什么我不能以字符串形式保存'.html'文件。

import boto3
from io import StringIO
s3 = boto3.client('s3')

display = # Altair Charting

str_obj = StringIO() # instantiate in-memory string object
display.save(str_obj, 'html') # saving to memory string object
buf = str_obj.getvalue().encode() # convert in-memory string to bytes

# Upload as bytes
s3.put_object(
    Bucket=BUCKET, 
    Key=f'{DASHBOARD}{mkt_type}/{symbol}/index.html', 
    Body=buf
    )

你可以通过字符串形式从'display'获取HTML内容。尝试使用s3.put_object(Bucket=BUCKET, Key='index.html', Body=s)将包含HTML文档内容的字符串s存储到指定的Bucket和Key中。 - jarmod
我认为我按照您的建议实现了,但是内容没有存储到S3。 - smgeneralist
我不知道为什么这是个问题... 如果你有其他建议,欢迎分享 - smgeneralist
请注意,boto3文档指出upload_fileobj()期望传递给它的文件对象处于二进制模式,因此io.BytesIO()可能比io.StringIO()更合适。话虽如此,使用s3.upload_file()上传现有文件非常简单,使用s3_put_object()将字符串写入文件也很简单。我建议先尝试其中一个,因为如果您无法解决这个问题,那么就有更大的问题需要解决。 - jarmod
1个回答

3

来自boto3文档: put_object

Body=b'bytes'|file,

这意味着Body应该是文件句柄或字节字符串。 因此,上传方式有(至少)两种:

通过将文件句柄传递给Body参数:

with open('index.hml', 'rb') as f:
    s3.put_object(Bucket=BUCKET, Key=f'{DASHBOARD}{mkt_type}/{symbol}/index.html', Body=f)

如果传递一个字节串给Body(假设display.save()返回字符串):

buf = display.save('str.html').encode() # converting str to bytes
s3.put_object(Bucket=BUCKET, Key=f'{DASHBOARD}{mkt_type}/{symbol}/index.html', Body=buf)

是的,display.save() 不会直接返回一个字符串,但你帮我解决了问题。谢谢。 - smgeneralist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接