【问题标题】:Boto3 S3: TypeError: coercing to Unicode: need string or buffer, file foundBoto3 S3:TypeError:强制转换为 Unicode:需要字符串或缓冲区,找到文件
【发布时间】:2016-02-23 18:56:04
【问题描述】:

尝试将文件上传到 S3:

    # boto3 s3 client
    s3.put_object(Bucket=self.bucket,
                  Body=open(upload_file, 'rb'),
                  Key=k.key,
                  SSECustomerAlgorithm='AES256',
                  SSECustomerKey=base64.b64encode(data_key),
                  SSECustomerKeyMD5=base64.b64encode(data_key_md5)
                  )

并在这一行出错:

TypeError: coercing to Unicode: need string or buffer, file found

我的upload_file 变量是<type 'file'>dir

['__class__', '__delattr__', '__doc__', '__enter__', '__exit__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'closed', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'mode', 'name', 'newlines', 'next', 'read', 'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell', 'truncate', 'write', 'writelines', 'xreadlines']

切换到open(upload_file, 'rb').read() 无济于事。我的文件也可能很大(1gb pr 所以),将它们保留为字符串是不合理的。

我知道如果我将upload_file 设置为文件路径,它会起作用,但我的磁盘上没有这个文件,它是通过表单提交的。

更新

这很奇怪,但是当我使用测试文件或字符串(为了测试)时遇到了类似的问题:

TypeError: expected string or buffer

这是对:

# boto3 s3 client
s3.put_object(Bucket=self.bucket,
    # put existing filr
    Body=open('/tml/existing-file', 'rb'), # adding read() wont help
    # ...
)

字符串也一样:

# boto3 s3 client
s3.put_object(Bucket=self.bucket,
    # put existing filr
    Body='some random string',
    # ...
)

【问题讨论】:

  • 设置Body=open(upload_file, 'rb').read()时遇到什么错误?
  • @wilbur *** TypeError: coercing to Unicode: need string or buffer, file found 这个文件来自表单,<open file '<fdopen>', mode 'w+b' at ***>
  • 如果您只是将upload_file 传递给Body 而不是尝试打开它呢?
  • @wilbur 如果我通过了upload_file 我得到了错误TypeError: expected string or bufferupload_file.read() 相同
  • 您能提供完整的回溯吗?

标签: python python-2.7 boto boto3


【解决方案1】:

我建议您将输入流写入临时文件并使用Bucket.upload_file 传输文件。将大文件保存在 Web 服务应用程序的内存中并不好。假设您有多个并发上传请求,这将消耗大量内存。

import tempfile
import shutil
file_ = file_like_object_from_form_submit
with tempfile.NamedTemporaryFile() as tmpfile:
    shutil.copyfileobj(file_, tmpfile)
    tmpfile.flush()
    self.bucket.upload_file(tmpfile.name, path)

【讨论】:

  • 试图避免这种情况。但会尽力给你反馈
  • 只对了一半。类文件对象对于put_object 是有效的主体,但对于upload_file 则不是
  • @jordon-phillips 你有更好的主意吗?
  • 根据乔丹的评论修改了答案。
【解决方案2】:

不知道为什么我不能让它与 boto3 一起工作,但这里的代码与以前的 boto2 版本一起工作。唯一的区别是:根据官方文档,您需要在 header 中添加 put 参数: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html 在我的代码案例示例中,它看起来像:

    headers.update({
        'x-amz-server-side-encryption-customer-algorithm': 'AES256',
        'x-amz-server-side-encryption-customer-key': base64.b64encode(data_key),
        'x-amz-server-side-encryption-customer-key-MD5': base64.b64encode(data_key_md5)
    })

    k.set_contents_from_file(upload_file, headers=headers)

如您所见,upload_file 在这种情况下工作正常。

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 2015-02-01
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多