【问题标题】:Download a file from s3 to local and then send in post request从 s3 下载文件到本地,然后发送 post 请求
【发布时间】:2021-11-16 17:34:53
【问题描述】:

假设我在 s3 存储桶中有这个文件:

s3://qq-dag/production/special-db/xx.gz

我现在希望有人能够向我发送此路径,并且我会自动使用此文件路径以便在我发出的发布请求中发送文件本身。

我想到的解决方案是首先将其下载到本地,然后以某种方式使用我的本地文件路径发送 post 请求。它可以工作吗?任何人都可以发布我如何做到的示例?

我尝试了类似的方法,但我尝试使用此代码的任何变体的每个解决方案都不断出错:

file = r'C:\Users\jhon.king\files\xx.gz'

bucket = 'qq-dag/production/special-db'
key='xx.gz'
     
s3client = boto3.client('s3')
s3client.download_file(bucket, key, file)









//now post request part
files=[
  ('file',('xx.gz',ocpen(''r'C:\Users\jhon.king\files\xx.gz,'rb'),'text/gz'))
]
headers = {
'X-Atlassian-Token': 'nocheck',
 'Authorization': 'Basic Ymyb3dpdHo6kkczEyMzQ=',

}
response = requests.request("POST", url, headers=headers, data=payload, files=files)

我确定我以某种方式误用了存储桶或文件名部分。谁能帮帮我?

我根据下面的答案尝试下载这个我不断收到错误

​import os
prefix = 'user/mynew-research'
file = "mymyjira.gz"
#s3.Bucket(bucket).download_file(f'{prefix}/{file}', file)
​
AWS_KEY_ID = "kUvRWN8xabRdg++lUP84A3g"
AWS_ACCESS_KEY = 'AKIAJPQ'
bucket = 'my-research'
​
s3=boto3.resource(
    service_name='s3',
    region_name='us-east-1',
    aws_access_key_id=AWS_KEY_ID,
    aws_secret_access_key=AWS_ACCESS_KEY
)
s3.Bucket(bucket).download_file(f'{prefix}/{file}', file)

ClientError: 调用 HeadObject 操作时发生错误 (400): Bad Request

【问题讨论】:

  • 你能显示错误信息吗?

标签: amazon-s3 python-requests


【解决方案1】:

下载文件一共使用bucket/path/file

>>> bucket = "s3_bucket"
>>> prefix = "path/to"
>>> file = "file.gz"
>>> s3.Bucket(bucket).download_file(f'{prefix}/{file}', file)

我看到您正在下载文件 s3client.download_file(bucket, key, file),但您正在发布尝试从带有请求的 s3 路径上传,但您将无法这样做。

requests 仅发送 url(在您的示例中)而不是文件内容,您将请求与 S3 位置混合,但您需要单独使用它。 boto3 将授予您下载文件或使用S3 执行某些操作的权限,但requests 只能发送您已经在内存中的数据或文件或数据等。

所以我会下载文件(或从 S3 获取文件)然后open 要发送的文件。

# Your download file code goes here
# And now the file "xx.gz" exists in the file system

response = requests.post(
    url=url,
    headers=headers,
    files={'file_or_name_needed': open('xx.gz', 'rb')},
    data=data,
)

这是用于上传文件的answer

在实例化s3 客户端时

AWS_KEY_ID = os.environ['AWS_KEY_ID']
AWS_ACCESS_KEY = os.environ['AWS_ACCESS_KEY']

boto3.resource(
    service_name='s3',
    region_name='xx-yyyy-i',
    aws_access_key_id=AWS_KEY_ID,
    aws_secret_access_key=AWS_ACCESS_KEY,
)

编辑:

您无需将文件添加到prefix,因为fstring 可以解决问题。

prefix = 'my-research/user/mynew-research'
file = "mymyjira.gz"

fstring 的结果是my-research/user/mynew-research/mymyjira.gz

我自己测试过,效果很好:

import boto3
import os
import requests

config = dict(
    service_name="s3",
    region_name="eu-west-1",
    aws_access_key_id=os.environ["AWS_KEY"],
    aws_secret_access_key=os.environ["AWS_SECRET"],
)
s3_ = boto3.resource(**config)

bucket = "bucket"
prefix = "path/to"
file = "file"

s3_.Bucket(bucket).download_file(f"{prefix}/{file}", file)

response = requests.post(
    url="https://httpbin.org/post",
    files={
        "myfile": (open(file, "rb")),
    },
)

# or if you don't want to download the file and just read it
s3_response = s3_client.get_object(Bucket=bucket, Key=f"{prefix}/{file}")

response = requests.post(
    url="https://httpbin.org/post",
    files={
        "myfile": (s3_response["Body"]).read(),
    },
)

特别注意bucketpathfile
假设存储桶名为test-bucket,文件位于test_data/regression/evidence.gz
代码应该是s3.Bucket("test-bucket").download_file("test_data/regression/evidence.gz", "evidence.gz")

【讨论】:

  • 但是连下载本身都不下载文件
  • 我有一个错误,谢谢。我编辑了问题
  • 但是脚本是否引发错误? boto3 的下载文件会将文件下载到您正在运行脚本的同一文件夹中。下载文件s3.Bucket(bucket).download_file(f'{prefix}/{file}', file)
  • 如果你想将文件下载到另一个目录,改变第二个参数。
  • 当我尝试下载时出现此错误 ClientError: An error occurred (404) when calling HeadObject operation: Not Found
猜你喜欢
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 2019-07-19
  • 1970-01-01
  • 2021-10-24
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多