Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Heroku 从专用AWS S3存储桶在烧瓶中提供静态文件_Heroku_Amazon S3_Flask_Boto3_Static Files - Fatal编程技术网

Heroku 从专用AWS S3存储桶在烧瓶中提供静态文件

Heroku 从专用AWS S3存储桶在烧瓶中提供静态文件,heroku,amazon-s3,flask,boto3,static-files,Heroku,Amazon S3,Flask,Boto3,Static Files,我正在开发一个运行在Heroku上的Flask应用程序,允许用户上传图像。该应用程序有一个页面,在表格中显示用户的图像 出于开发目的,我将上传的文件保存到Heroku的文件系统中,一切正常:图像正确加载和显示(我使用的是最后一种方法,表示使用了send_from_directory())。现在我已经将存储移到了S3,我正在尝试调整代码。我使用boto3将文件上传到bucket:它工作正常我的疑问与用用户的图像填充用户页面的下载有关 如前所述,我可以将文件设置为“public read”并使用UR

我正在开发一个运行在Heroku上的Flask应用程序,允许用户上传图像。该应用程序有一个页面,在表格中显示用户的图像

出于开发目的,我将上传的文件保存到Heroku的文件系统中,一切正常:图像正确加载和显示(我使用的是最后一种方法,表示使用了send_from_directory())。现在我已经将存储移到了S3,我正在尝试调整代码。我使用boto3将文件上传到bucket:它工作正常我的疑问与用用户的图像填充用户页面的下载有关

如前所述,我可以将文件设置为“public read”并使用URL(我认为这就是URL),但我宁愿不保留对文件的自由访问权因此,我的解决方案尝试将文件下载到Heroku的文件系统中,并再次使用send_from_directory()为映像提供服务,如下所示:

...
<img src="{{ url_for('app.download_image',
                     resource=resource) }}" height="120" width="120">
...
app.py

@app.route('/download/<resource>')
def download_image(resource):
    """ resource: name of the file to download"""
    s3 = boto3.client('s3',
                      aws_access_key_id=current_app.config['S3_ACCESS_KEY'],
                      aws_secret_access_key=current_app.config['S3_SECRET_KEY'])

    s3.download_file(current_app.config['S3_BUCKET_NAME'],
                     resource,
                     os.path.join('tmp',
                                  resource))

    return send_from_directory('tmp',  # Heroku's filesystem
                               resource,
                               as_attachment=False)
@app.route(“/download/”)
def下载_图像(资源):
“”“资源:要下载的文件的名称”“”
s3=boto3.client('s3',
aws\u access\u key\u id=当前的应用程序配置['S3\u access\u key'],
aws_secret_access_key=当前_app.config['S3_secret_key'])
s3.下载_文件(当前_app.config['s3_BUCKET_NAME'],
资源,,
os.path.join('tmp',
(资源)
返回send_from_目录('tmp'),#Heroku的文件系统
资源,,
as_附件=错误)
然后,在模板中,我生成图像的URL,如下所示:

...
<img src="{{ url_for('app.download_image',
                     resource=resource) }}" height="120" width="120">
...
。。。
...
这是可行的,但出于某些原因,我认为这不是正确的方法:其中,我应该管理Heroku的文件系统,以避免在dynos重新启动之间耗尽所有空间(我应该从文件系统中删除映像)

考虑到性能,哪种方法是最好的/首选的?
非常感谢

首选的方法是只对图像进行重定向,然后返回到该URL。这使文件在S3中保持私有,但会生成一个临时的、有时间限制的URL,可用于直接从S3下载文件。这将大大减少服务器上的工作量,以及服务器所消耗的数据传输量。大概是这样的:

@app.route('/download/<resource>')
def download_image(resource):
    """ resource: name of the file to download"""
    s3 = boto3.client('s3',
                      aws_access_key_id=current_app.config['S3_ACCESS_KEY'],
                      aws_secret_access_key=current_app.config['S3_SECRET_KEY'])

    url = s3.generate_presigned_url('get_object', Params = {'Bucket': 'S3_BUCKET_NAME', 'Key': resource}, ExpiresIn = 100)
    return redirect(url, code=302)
@app.route(“/download/”)
def下载_图像(资源):
“”“资源:要下载的文件的名称”“”
s3=boto3.client('s3',
aws\u access\u key\u id=当前的应用程序配置['S3\u access\u key'],
aws_secret_access_key=当前_app.config['S3_secret_key'])
url=s3.generate_presigned_url('get_object',Params={'Bucket':'s3_Bucket_NAME','Key':resource},ExpiresIn=100)
返回重定向(url,代码=302)

如果您不喜欢该解决方案,您至少应该研究从S3流式传输文件内容,而不是将其写入文件系统。

只想指出,此方法可以绕过每个用户的安全控制,因为任何具有该链接的人都可以在分配的时间窗口内访问该文件。