本文介绍了将文件从s3存储桶下载到USERS计算机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将文件从s3存储桶下载到用户计算机.

Download file from s3 Bucket to users computer.

我正在为React应用开发Python/Flask API.当用户单击前端上的下载"按钮时,我想将适当的文件下载到他们的计算机上.

I am working on a Python/Flask API for a React app. When the user clicks the Download button on the Front-End, I want to download the appropriate file to their machine.

import boto3s3 = boto3.resource('s3')s3.Bucket('mybucket').download_file('hello.txt', '/tmp/hello.txt')

import boto3s3 = boto3.resource('s3')s3.Bucket('mybucket').download_file('hello.txt', '/tmp/hello.txt')

我当前正在使用一些代码来找到downloads文件夹的路径,然后将该路径以及他们尝试下载的存储桶中的文件作为第二个参数插入到download_file()中.

I am currently using some code that finds the path of the downloads folder and then plugging that path into download_file() as the second parameter, along with the file on the bucket that they are trying to download.

这在本地有效,并且测试运行正常,但是一旦部署,我就遇到了问题.该代码将找到SERVER的下载路径,并在该位置下载文件.

This worked locally, and tests ran fine, but I run into a problem once it is deployed. The code will find the downloads path of the SERVER, and download the file there.

解决此问题的最佳方法是什么?我已经研究过,但找不到能够将文件从s3存储桶下载到users downloads文件夹的好的解决方案.任何帮助/建议都将不胜感激.

What is the best way to approach this? I have researched and cannot find a good solution for being able to download a file from the s3 bucket to the users downloads folder. Any help/advice is greatly appreciated.

推荐答案

您不需要将文件保存到服务器.您可以将文件下载到内存中,然后构建一个包含文件的Response对象.

You should not need to save the file to the server. You can just download the file into memory, and then build a Response object containing the file.

from flask import Flask, Response
from boto3 import client

app = Flask(__name__)


def get_client():
    return client(
        's3',
        'us-east-1',
        aws_access_key_id='id',
        aws_secret_access_key='key'
    )


@app.route('/blah', methods=['GET'])
def index():
    s3 = get_client()
    file = s3.get_object(Bucket='blah-test1', Key='blah.txt')
    return Response(
        file['Body'].read(),
        mimetype='text/plain',
        headers={"Content-Disposition": "attachment;filename=test.txt"}
    )


app.run(debug=True, port=8800)

这对于小文件是可以的,对于用户而言,没有任何有意义的等待时间.但是,对于较大的文件,这会严重影响UX.该文件将需要完全下载到服务器,然后再下载给用户.因此,要解决此问题,请使用get_object方法的Range关键字参数:

This is ok for small files, there won't be any meaningful wait time for the user. However with larger files, this well affect UX. The file will need to be completely downloaded to the server, then download to the user. So to fix this issue, use the Range keyword argument of the get_object method:

from flask import Flask, Response
from boto3 import client

app = Flask(__name__)


def get_client():
    return client(
        's3',
        'us-east-1',
        aws_access_key_id='id',
        aws_secret_access_key='key'
    )


def get_total_bytes(s3):
    result = s3.list_objects(Bucket='blah-test1')
    for item in result['Contents']:
        if item['Key'] == 'blah.txt':
            return item['Size']


def get_object(s3, total_bytes):
    if total_bytes > 1000000:
        return get_object_range(s3, total_bytes)
    return s3.get_object(Bucket='blah-test1', Key='blah.txt')['Body'].read()


def get_object_range(s3, total_bytes):
    offset = 0
    while total_bytes > 0:
        end = offset + 999999 if total_bytes > 1000000 else ""
        total_bytes -= 1000000
        byte_range = 'bytes={offset}-{end}'.format(offset=offset, end=end)
        offset = end + 1 if not isinstance(end, str) else None
        yield s3.get_object(Bucket='blah-test1', Key='blah.txt', Range=byte_range)['Body'].read()


@app.route('/blah', methods=['GET'])
def index():
    s3 = get_client()
    total_bytes = get_total_bytes(s3)

    return Response(
        get_object(s3, total_bytes),
        mimetype='text/plain',
        headers={"Content-Disposition": "attachment;filename=test.txt"}
    )


app.run(debug=True, port=8800)

这将以1MB的块大小下载文件,并在下载文件时将其发送给用户.这两个文件均已通过40MB .txt文件进行了测试.

This will download the file in 1MB chunks and send them to the user as they are downloaded. Both of these have been tested with a 40MB .txt file.

这篇关于将文件从s3存储桶下载到USERS计算机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-04 16:02
查看更多