How to upload a base64 encoded string to s3 and access the url in html file in python

10,636

Solution 1

The answer for my question is use boto set_meta_data and set the content type to 'image/jpeg'. Then it served my purpose. Now I am able to open the image in browser using public url

conn = boto.connect_s3(AWS_ACCESS_KEYXXX, AWS_SECRET_KEYXXX)
bucket = conn.get_bucket(AWS_BUCKET_NAMEXXX)
k = Key(bucket)
k.key = s3_file_name
k.set_metadata('Content-Type', 'image/jpeg')
k.set_contents_from_file(file_obj)

Solution 2

set_contents_from_string(base64.b64decode(data)) worked for me

Full code

import boto
from boto.s3.connection import S3Connection
from boto.s3.key import Key
# import urllib
# from io import BytesIO
AWS_ACCESS_KEY = os.environ.get('AWS_ACCESS_KEY') 
AWS_SECRET_KEY = os.environ.get('AWS_SECRET_KEY')
AWS_BUCKET_NAME = os.environ.get('S3_BUCKET_NAME')
import base64

I'm doing this in a django view, so I read in the base64 data and assign it to a variable called cover_art at this point. Then I save it to S3 like so:

connection = boto.connect_s3()
bucket = connection.get_bucket(AWS_BUCKET_NAME)
cloudfile = Key(bucket)
path = "images/" + me.username + "/" + "cover-image-001.jpg"
cloudfile.key = path
cloudfile.set_contents_from_string(base64.b64decode(cover_art))
cloudfile.set_metadata('Content-Type', 'image/jpeg') # from https://stackoverflow.com/a/22730676 and https://stackoverflow.com/questions/16156062/using-amazon-s3-boto-library-how-can-i-get-the-url-of-a-saved-key
cloudfile.set_acl('public-read')

Extra comment

I was completely new to base64 encoding a couple of hours ago, so wasn't even sure what I should be working with using boto. Just in case you're feeding in the wrong thing to boto, here's an extra note on that variable "cover_art" I used.

Say the data looks like this:

data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFR...

That's what I'd need to put into a webpage if for example I want to display the image like this

<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFR...">

However, here in python code, the bit I feed to boto is that without the introduction. So my variable looks like this:

cover_art = "/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFR..."

I'm actually collecting it from a form which looks like

<input name="cover_art" type="hidden" value="/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQV...">

(If you're also using a form and want to check this in the browser upon submission, try grabbing the form using javascript and then displaying it, sth. like alert(theForm.innerHTML))

Note, there are no funny-looking characters, it does NOT look like ÿØÿà...

(Hopefully you can tell by the language I'm using that I'm a n00b!)

BTW I'm posting this because for some reason I couldn't get the set_contents_from_file(file_obj) method to work for me... thanks for posting your answer though, good to see that method worked for you.

Solution 3

from boto.s3.connection import S3Connection
from boto.s3.key import Key
import base64
picture = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlcAAAMfCAY...example"
conn = S3Connection('ACCESS', 'SECRET', host='HOST')
bucket = conn.get_bucket('BUCKET')
k = Key(bucket)
k.key = 'filename.png'
picture = picture.replace("data:image/png;base64,","")
k.set_contents_from_string(base64.b64decode(picture))
k.set_metadata('Content-Type', 'image/png')
Share:
10,636
kishore
Author by

kishore

Updated on June 14, 2022

Comments

  • kishore
    kishore almost 2 years

    I have a base64 string. This string is base64 equivalent to image. Now this file should be uploaded to S3 and should be accessed using the s3 url directly in my browser or html file. I have tried a couple of methods but failed to open the image in browser, it is just downloading into my box.

    Method 1: use the botoS3 method set_contents_from_string

    Method 2: convert the base64 to StringIO and use set_contents_from_file

    Method 3: Save the base64 to temp file and then use the method set_contents_from_file.

    All the above methods I used just downloading the file in my browser, they are not recognizing it as image