如何在使用PIL修改文件后从文件上传表单上传文件到s3?

时间:2015-01-18 23:54:35

标签: python amazon-s3 flask boto

以下是代码内容:

app.config['DEBUG']= True


if request.method == 'POST' and request.form['file_submit']:
        print request.form
        print request.files['image']
        if request.files['image']:
            print 'foshhh'
            image_file = request.files['image']
            img = PIL.Image.open(image_file.stream)
            print img
            if request.form['make_transparent']:
                threshold=100
                print 'changin sizesd'
                dist=5
                # np.asarray(img) is read only. Wrap it in np.array to make it modifiable.
                arr=np.array(np.asarray(img))
                r,g,b,a=np.rollaxis(arr,axis=-1)
                mask=((r>threshold)
                    & (g>threshold)
                    & (b>threshold)
                    & (np.abs(r-g)<dist)
                    & (np.abs(r-b)<dist)
                    & (np.abs(g-b)<dist)
                    )
                arr[mask,3]=0
                img=Image.fromarray(arr,mode='RGBA')
            if request.form['change_size']:
                img = Image.open('out.png')
                img.thumbnail(size,Image.ANTIALIAS)
                img.save('out.png',"PNG")

            img.save('out.png',"PNG")
            print os.path.getsize("out.png")   #from answer
            assert os.path.isfile("out.png")   #from answer
            conn = S3Connection(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)
            b = conn.get_bucket('snappie.watermarks')
            k = Key(b)
            k.key = "test.png"
            k.set_metadata('Content-Type', 'image/png')
            k.set_contents_from_filename("out.png")
            print "got file"
            return redirect("https://s3.amazonaws.com/snappie.watermarks/"+filename)
        else:
            print 'please upload a file to submit the form!'

这是html表单:

   <form method="POST" enctype="multipart/form-data" name="file_submit">
            <label>Choose png here.<input type="file" name="image"></label>
            <input type="hidden" name="file_submit" value="yes">
            Change size?<input type="checkbox" name="change_size" value="yes"/>
            Make Background Transparent?<input type="checkbox" name="make_transparent" value="yes"\><br><br>
            <input type="submit" value="submit">
    </form>

问题的一部分是它并没有真正给我一个错误日志。您可以看到,有两个复选框可以修改图像文件。如果检查第一个,它的“透明”#34;如果选中第二个,则会改变大小。

我认为在转换和修改图像对象的类型时遇到问题,特别是当它传递到此对象时:k.set_contents_from_filename("out.png")

这里有什么帮助吗?这是服务器日志给我的唯一输出:

GET
127.0.0.1 - - [18/Jan/2015 15:42:26] "GET / HTTP/1.1" 200 -
POST
ImmutableMultiDict([('file_submit', u'yes')])
<FileStorage: u'birnam_wood.jpg' ('image/jpeg')>
foshhh
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=100x100 at 0x7FDDF4CA6C68>
127.0.0.1 - - [18/Jan/2015 15:42:32] "POST / HTTP/1.1" 400 -

3 个答案:

答案 0 :(得分:2)

为了正确调试,您确实需要查看回溯。它会告诉你出了什么问题: - )!!

否则:我猜你的一般方法(首先在文件系统中创建一个图像文件,然后使用boto进行上传)很好。但是,出于调试目的,您可以检查img.save('out.png',"PNG")留下的内容。出于调查目的,您可以测试文件是否存在,否则引发异常:assert os.path.isfile("out.png")。此外,您可能希望使用os.path.getsize("out.png")打印文件大小。据我记得使用boto,k.set_contents_from_filename("out.png")是正确的做法。

也就是说,你的做事顺序是正确的。最有可能是S3存在身份验证/连接问题,正如Dmitry已经指出的那样。通过查看Traceback可以找到此问题的详细信息。 boto回溯将包含错误AWS错误响应。

答案 1 :(得分:1)

请使用以下技巧查看boto发送给S3的所有原始http请求:

import httplib
httplib.HTTPConnection.debuglevel = 1

你也可以使用这个提示:

import logging
logging.basicConfig(filename="boto.log", level=logging.DEBUG)

在使用Web服务器测试功能之前,请尝试从默认的python控制台执行一些测试代码:

import httplib
httplib.HTTPConnection.debuglevel = 1

conn = boto.connect_s3(aws_access_key_id='some', aws_secret_access_key='some')
b = conn.get_bucket('snappie.watermarks')
k = Key(b)
k.key = "test.txt"
k.set_contents_from_string('12345')

之后请检查文件是否存在。无论如何,在所有操作之后你都应该执行:

key.make_public()

因为默认情况下所有新的桶对象都不公开。

答案 2 :(得分:0)

基本上,我认为服务器错误是在没有&#34;图像&#34; request.files字典中的对象,但请求已发送。因此服务器不知道该怎么做。我使用request.files.get(&#39; image&#39;)而不是request.files [&#39; image&#39;]来修复它。因此,如果没有图像,则返回None而不是给出键错误。

虽然我知道每个人都想要一个引用,但仍然没有引用,因为烧瓶中的这种服务器错误似乎没有返回追溯。只是一个&#34;错误的请求&#34;浏览器中的错误消息。