2012-09-24 13 views
19

¿Hay alguna manera factible de cargar un archivo que se genera dinámicamente a amazon s3 directamente sin crear primero un archivo local y luego cargarlo al servidor s3? Yo uso Python. GraciasCómo cargar un archivo en S3 sin crear un archivo local temporal

+0

Las respuestas a continuación explican dos maneras de hacer esto . Pero si alguna vez se topa con una API que solo puede tomar archivos, es posible que desee ver 'tempfile.TemporaryFile'; con los parámetros correctos, obtienes un objeto similar a un archivo, lo más parecido a no ser un archivo real como sea posible. (En POSIX, esto significa que no tiene entrada de directorio y no está respaldado en el disco a menos que sea necesario; en Windows es en realidad un objeto envoltorio alrededor de un objeto de archivo que existe en el directorio temporal hasta que lo cierra, lo cual no siempre es bueno lo suficiente, entonces puede que tenga que PyWin32 'CreateFile' y hacer un código más complicado para obtener lo que desea). – abarnert

+0

Por el momento boto no tiene funcionalidad para esto. El método 'Key.open_write()' aún no está implementado. Una vez que lo tenga, tendrá la respuesta. 'set_contents_from_stream()' presuntamente puede leer de un objeto de transmisión pero en realidad espera un archivo ... No sé si se puede usar de alguna manera ... – DejanLekic

Respuesta

2

Supongo que estás usando boto. boto 's Bucket.set_contents_from_file() aceptará un objeto StringIO, y cualquier código que haya escrito para escribir datos en un archivo debe ser fácilmente adaptable para escribir en un objeto StringIO. O si genera una cadena, puede usar set_contents_from_string().

+0

Intenté en python file = request.file ['name'] set_contents_from_file (file.readlines()), pero necesita una cadena para iterar y obtener una cadena pero me da ** AttributeError: el objeto 'str' no tiene atributo 'tell' ** – Shashank

+1

Eso es porque estás pasando una cadena, no un objeto 'StringIO' como sugerí ... – kindall

+0

Ohh sí, estás en lo correcto, pero en ambos sentidos StringIO (archivo) o StringIO (file.readlines()), el archivo cargado a s3 pero no se pudo abrir muestra solo el símbolo en blanco browser .... – Shashank

9

El boto de biblioteca Key objeto tiene varios métodos que le pueden interesar:

Para un ejemplo del uso set_contents_from_string, ver Storing Data sección de la documentación boto, pegado aquí para completar:

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

Pero ¿cómo es posible en ** set_contents_from_file **, y acepta el archivo que almacenado localmente en el disco – Shashank

+0

@shihon no entiendo su pregunta. – jterrace

+1

Veo que obtuve un archivo usando una solicitud como ** file = request.file ['name'] ** y luego lo guardo localmente ** os.save (os.path.join (path, file)) **, desde allí configuro la clave s3 y ** set_contents_from_filename (os.path.join (ruta, archivo)) **, allí necesito guardar el archivo directamente en s3 en lugar de guardarlo primero localmente y luego en s3 ... – Shashank

6

usted podría utilizar BytesIO de la biblioteca estándar de Python.

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

Aquí se muestra un ejemplo de descargar una imagen (utilizando las solicitudes de biblioteca) y subirlo a S3, sin necesidad de escribir en un archivo local:

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

Esto es lo que estaba buscando, gracias – 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) 
Cuestiones relacionadas