2012-09-24 108 views
19

是否有任何可行的方式将上传动态生成的文件直接上传到amazon s3而无需先创建本地文件然后上传到s3服务器?我使用python。谢谢如何将文件上传到S3而不创建临时本地文件

+0

的答案解释两种方法可以做到这一点。但是如果你遇到一个只能获取文件的API,你可能想看看'tempfile.TemporaryFile';使用正确的参数,您将获得类似文件的对象,尽可能接近不成为真实文件。 (在POSIX上,这意味着它没有目录项,并且除非必要,它不会被备份到磁盘;在Windows上,它实际上是一个临时目录周围存在的文件对象的包装对象,直到您关闭它为止,这并不总是好的足够了,所以你可能需要PyWin32'CreateFile'并且做一些更复杂的代码来获得你想要的)。 – abarnert

+0

目前boto没有这方面的功能。 'Key.open_write()'方法尚未实现。一旦它是你将有答案。 ''set_contents_from_stream()'据称可以从流对象读取,但它实际上期望一个文件...我不知道它是否可以以某种方式使用... – DejanLekic

回答

2

我假设你使用的是botobotoBucket.set_contents_from_file()将接受一个StringIO对象,并且您写入的用于将数据写入文件的任何代码都应该可以很容易地适用于写入StringIO对象。或者如果你生成一个字符串,你可以使用set_contents_from_string()

+0

我试过在python file = request.file ['name'] set_contents_from_file (file.readlines()),但它需要一个字符串,所以我迭代并获得字符串,但它给了我** AttributeError:'str'对象没有属性'tell'** – Shashank

+1

这是因为你传递一个字符串,而不是一个'StringIO'对象,因为我建议... – kindall

+0

哦,是的,你是正确的,但在两种方式StringIO(文件)或StringIO(file.readlines()),文件上传到S3,但无法打开只显示空白符号浏览器.... – Shashank

9

boto库的Key对象有几个方法,你可能感兴趣的:

对于使用的例子set_contents_from_string,看到博托文档Storing Data部分,粘贴在这里的完整性:

>>> from boto.s3.key import Key 
>>> k = Key(bucket) 
>>> k.key = 'foobar' 
>>> k.set_contents_from_string('This is a test of S3') 
+0

但是如何在** set_contents_from_file **中可能,并且它接受文件本地存储在磁盘上 – Shashank

+0

@shihon我不明白你的意思题。 – jterrace

+1

看到我用** file = request.file ['name'] **得到了一个文件,然后我将它保存在本地** os.save(os.path.join(path,file))**,from那里我设置S3键和** set_contents_from_filename(os.path.join(路径,文件))**,那么我需要直接在S3上保存文件,而不是先保存在本地,然后在S3上... – Shashank

6

你可以使用BytesIO从Python标准库。

from io import BytesIO 
bytesIO = BytesIO() 
bytesIO.write('whee') 
bytesIO.seek(0) 
s3_file.set_contents_from_file(bytesIO) 
13

下面是一个例子下载的图像(使用请求库),并上传到S3,而无需编写本地文件:下面

import boto 
from boto.s3.key import Key 
import requests 

#setup the bucket 
c = boto.connect_s3(your_s3_key, your_s3_key_secret) 
b = c.get_bucket(bucket, validate=False) 

#download the file 
url = "http://en.wikipedia.org/static/images/project-logos/enwiki.png" 
r = requests.get(url) 
if r.status_code == 200: 
    #upload the file 
    k = Key(b) 
    k.key = "image1.png" 
    k.content_type = r.headers['content-type'] 
    k.set_contents_from_string(r.content) 
+0

这就是我一直在寻找的,谢谢 – noahandthewhale

0
def upload_to_s3(url, **kwargs): 
    ''' 
    :param url: url of image which have to upload or resize to upload 
    :return: url of image stored on aws s3 bucket 
    ''' 

    r = requests.get(url) 
    if r.status_code == 200: 
     # credentials stored in settings AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY 
     conn = boto.connect_s3(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, host=AWS_HOST) 

     # Connect to bucket and create key 
     b = conn.get_bucket(AWS_Bucket_Name) 
     k = b.new_key("{folder_name}/{filename}".format(**kwargs)) 

     k.set_contents_from_string(r.content, replace=True, 
            headers={'Content-Type': 'application/%s' % (FILE_FORMAT)}, 
            policy='authenticated-read', 
            reduced_redundancy=True) 

     # TODO Change AWS_EXPIRY 
     return k.generate_url(expires_in=AWS_EXPIRY, force_http=True) 
相关问题