【问题标题】:Uploading image to S3 (boto + GAE)将图像上传到 S3 (boto + GAE)
【发布时间】:2012-09-02 10:21:53
【问题描述】:

我正在尝试使用我的 GAE python 应用程序设置 s3(使用 boto)来存储用户上传的图像。目前我收到以下错误:

File "/Users/phyzikz/project/boto/s3/key.py", line 936, in set_contents_from_file spos = fp.tell()
AttributeError: 'str' object has no attribute 'tell'

我不知道为什么会这样——上传的文件应该是 png。这是进行上传的代码:

class Settings(Handler):
    def get(self):
        self.render('settings.html')

    def post(self):
        image = self.request.get('image')

        if image:
            connection = S3Connection('<ak>','<sak>')
            bucket = connection.create_bucket('<s3bucket>')
            k = Key(bucket)
            k.key = '/pictures/users/'+ str(self.user.key().id())
            k.set_contents_from_file(image)

如果它有帮助,当用 set_contents_from_string('some string') 替换 set_contents_from_file(image) 时,它在调试时工作得很好。我一定错过了一些简单的东西。这是html:

<form method='post' action='/settings' enctype='multipart/form-data'>
    <input type='file' name='image'>
    <input type='submit'>
</form>

免责声明:我是 python 和 SO 的新手(这是我的第一个问题!)如有必要,对改进问题的措辞进行任何编辑将不胜感激。

【问题讨论】:

    标签: python google-app-engine boto


    【解决方案1】:

    您需要将图像包装在 StringIO 实例中,使其看起来像一个文件对象

    Python 2.7.2+ (default, Oct  4 2011, 20:03:08) 
    [GCC 4.6.1] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> x = "123"
    >>> from StringIO import StringIO
    >>> y = StringIO(x)
    >>> y.tell()
    0
    >>> 
    

    所以在你的情况下,你会

    k.set_contents_from_file(StringIO(image))
    

    【讨论】:

    • 感谢蒂姆,这成功了!对其他人来说可能值得注意的是,在尝试了这个之后,我发现它也可以与 k.set_contents_from_string(image) 一起使用,而无需使用 StringIO。
    • @phyzikz:它不适用于 k.set_contents_from_string(image),在 s3 上上传后,您可以看到对象的大小以字节为单位,因为它只包含字符串...所以不值得
    【解决方案2】:

    如果您可以将您定义或分配fp 的代码(在方法中:set_contents_from_file 中的Key 类)放入,我们可以提供更好的帮助。但是,查看错误AttributeError: 'str' object has no attribute 'tell',很明显fp 不是文件对象。它是一个字符串对象,因此是错误的。由于您是 SO 新手,请先尝试自己更正代码,然后,如果您仍然无法解决问题,您可以粘贴您用于将 fp 更改为文件对象的代码。

    【讨论】:

    • 感谢您的快速响应。该方法是 boto s3 包的一部分(github.com/boto/boto/blob/develop/boto/s3/key.py - 第 847 行)。正如你所说,很明显 fp 不是文件对象,但鉴于 html 和请求的简单性,我无法弄清楚为什么它是一个字符串而不是我选择的 png。
    • 正如我在第 847 行看到的那样,fp 对象由调用者传递。第 847 行没有问题。问题出在fp。您能以某种方式查看您的代码并将您分配值的部分粘贴到fp 吗?您可以使用print fp, type(fp) 来检查fp 是什么。
    • repr(fp) 给了我一个充满文本的屏幕:'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xc1...'。在我的例子中,fp 是变量 image,它通过 post 表单传入,我传入 set_contents_from_file 方法。这有帮助吗?
    • 我正在当前工作目录中打开一个文件,这就是我得到的:- &gt;&gt;&gt; fp=open('diff.diff') &gt;&gt;&gt; print fp &lt;open file 'diff.diff', mode 'r' at 0x03CC96A8&gt; &gt;&gt;&gt; print type(fp) &lt;type 'file'&gt; 您还应该看到 @987654342 的输出@ 作为文件对象。不要为此使用 repr
    猜你喜欢
    • 2012-12-30
    • 2014-10-12
    • 2017-08-18
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 2015-12-11
    • 2011-11-01
    相关资源
    最近更新 更多