Esta pregunta se ha hecho muchas veces, pero mi caso es ligeramente diferente. Estoy tratando de crear una lambda que cree un archivo .html y lo cargue en S3. Funciona cuando el archivo se creó en el disco, luego puedo cargarlo así:
boto3.client('s3').upload_file('index.html', bucket_name, 'folder/index.html')
Entonces ahora tengo que crear el archivo en la memoria, para esto primero probé StringIO() . Sin embargo, .upload_file
arroja un error.
boto3.client('s3').upload_file(temp_file, bucket_name, 'folder/index.html') ValueError: Filename must be a string`.
Así que intenté usar .upload_fileobj()
pero luego aparece el error TypeError: a bytes-like object is required, not 'str'
Así que intenté usar Bytesio() que quiere que primero convierta el str a bytes, así que lo hice:
temp_file = BytesIO() temp_file.write(index_top.encode('utf-8')) print(temp_file.getvalue()) boto3.client('s3').upload_file(temp_file, bucket_name, 'folder/index.html')
Pero ahora solo carga un archivo vacío, a pesar de .getvalue()
muestra claramente que tiene contenido allí.
¿Qué estoy haciendo mal?
Si desea crear un objeto en Amazon S3 desde la memoria, use put_object()
:
import boto3 s3_client = boto3.client('s3') html = "<h2>Hello World</h2>" s3_client.put_object(Body=html, Bucket='my-bucket', Key='foo.html', ContentType='text/html')
Pero ahora solo carga un archivo vacío, a pesar de que .getvalue() muestra claramente que tiene contenido allí.
Cuando termina de escribir en un búfer de archivo, la posición permanece al final. Cuando carga un búfer, comienza desde la posición en la que se encuentra actualmente. Como está al final, no obtiene datos. Para solucionar esto, solo necesita agregar un seek (0) para restablecer el búfer al principio después de que termine de escribir en él. Su código se vería así:
temp_file = BytesIO() temp_file.write(index_top.encode('utf-8')) temp_file.seek(0) print(temp_file.getvalue()) boto3.client('s3').upload_file(temp_file, bucket_name, 'folder/index.html')