Question:
How do I store PNG / SVG / JPEG files in ReplitDB?
You can convert an image to a b64 string.
from base64 import b64decode, b64encode
def encode_image(path):
with open(path, "rb") as f:
binary = b64encode(f)
return binary
def decode_image(b64):
return b64decode(b64)
Actually, there are MANY ways to store images in ReplitDB. Now, let’s consider the fact that ReplitDB is only a key-value store, so it won’t let you store binary data such as PNG, SVG, or JPEG files within it. As an alternative, you can store image metadata like this:
image_metadata = {
"file_name": "example.png",
"file_type": "PNG",
"file_size": "1024 KB",
}
You can also host images externally using services like Imgur, AWS S3, or any other cloud storage service to upload and host your image files. These services will provide you with URLs that point to the hosted images. Alternatively, you can use this:
image_metadata["image_url"] = "https://example.com/path/to/your/image.png"
Whatever works to be honest, it doesn’t really matter.
@KAlexK I can see it’s getting closer. One problem, though. I’m using Flask and in the HTML, it asks the user for two images so the images aren’t actually stored in the Repl. This means that it does not allow me to use the encode_image()
function, because the path of the image isn’t actually in the Repl, rather a image the user imports via a <input type="file">
tag. What is a workaround for this?
I know you weren’t talking to me, but you can use this code to achieve what you want. It should work, but I haven’t tested it, so don’t blame me:
from flask import Flask, request, jsonify
from replit import db
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'jpg', 'jpeg', 'png', 'gif'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
def save_and_get_url(file):
if file.filename and allowed_file(file.filename):
file_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
file.save(file_path)
return f"https://{os.getenv('REPL_SLUG')}.{os.getenv('REPL_OWNER')}.repl.co/{file.filename}"
return None
@app.route('/upload', methods=['POST'])
def upload_file():
files = request.files
if 'image1' not in files or 'image2' not in files:
return "No files provided"
image_url1 = save_and_get_url(files['image1'])
image_url2 = save_and_get_url(files['image2'])
images_list = db.get('images', [])
images_list.append(image_url1)
images_list.append(image_url2)
db['images'] = images_list
return "Files uploaded and processed successfully"
@app.route('/get_images', methods=['GET'])
def get_images():
images_list = db.get('images', [])
return jsonify(images=images_list)
if __name__ == '__main__':
app.run(debug=True)
I don’t know exactly what the Flask image input returns, so this code converts the Pillow image to b64.
from base64 import b64decode, b64encode
from io import BytesIO
import re
from PIL import Image
def image_to_base64(image: Image):
output_buffer = BytesIO()
image.save(output_buffer, format='RGB')
byte_data = output_buffer.getvalue()
base64_str = b64encode(byte_data)
return base64_str
def base64_to_image(base64_str):
base64_data = re.sub('^data:image/.+;base64,', '', base64_str)
byte_data = b64decode(base64_data)
image_data = BytesIO(byte_data)
img = Image.open(image_data)
return img
Edit: oh, I didn’t even notice that the answer was already written by @sky
@Sky What would this exactly do? Store the image on the Repl? Some how access the actual file even though it isn’t stored in the Repl?
It returns a path. If I import a image named example.png
, it will return "example.png"
.
What do you mean? It is exactly as it appears. It takes the files from the request sent to your Flask route, checks if they are supported, saves the files to the upload folder ./uploads/
, then returns the image URL for the uploaded file, and finally saves it in the Replit DB.
Within the repl, correct? Is it temporary storage or permanent?
Yeah, unless you delete or clear ./uploads/
, the files would be permanent.
What part of this code actually creates and stores the images in the /uploads/
folder?
Oh, the function that does this is save_and_get_url()
.
In save_and_get_url()
, does the parameter file
accept a file path or a decoded / encoded BASE64 input?
In the save_and_get_url()
function, the file
parameter typically accepts a file object. It doesn’t handle encoded or decoded b64
input by default, but it can be setup to do so if needed.
from flask import Flask, request, jsonify
from io import BytesIO
from replit import db
import base64
import os
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'jpg', 'jpeg', 'png', 'gif'}
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']
def save_and_get_url(file_or_data):
if isinstance(file_or_data, bytes):
filename = 'base64_image.png'
file_data = base64.b64decode(file_or_data)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
with open(file_path, 'wb') as f:
f.write(file_data)
return f"https://{os.getenv('REPL_SLUG')}.{os.getenv('REPL_OWNER')}.repl.co/{filename}"
elif hasattr(file_or_data, 'filename') and allowed_file(file_or_data.filename):
file_path = os.path.join(app.config['UPLOAD_FOLDER'], file_or_data.filename)
file_or_data.save(file_path)
return f"https://{os.getenv('REPL_SLUG')}.{os.getenv('REPL_OWNER')}.repl.co/{file_or_data.filename}"
return None
@app.route('/upload', methods=['POST'])
def upload_file():
files = request.files
if 'image1' not in files or 'image2' not in files:
return "No files provided"
image_url1 = save_and_get_url(files['image1'].read())
image_url2 = save_and_get_url(files['image2'].read())
images_list = db.get('images', [])
images_list.extend([image_url1, image_url2])
db['images'] = images_list
return "Files uploaded and processed successfully"
@app.route('/get_images', methods=['GET'])
def get_images():
images_list = db.get('images', [])
return jsonify(images=images_list)
if __name__ == '__main__':
app.run(debug=True)
@Sky Problem is, I can’t convert example.png
to BASE64
because it is not yet a file so how could I access the code within the uploaded file example.png
? I’m not sure how to store it either, because I do not know how to make a File()
object.
What do you mean? The code I sent you handles the image byte data, then converts it to b64
. Wait, are you trying to send already converted data through it?
I’ll start from the top – the user inputs a image, I need to store it in my repl so I can access it later. The save_and_get_url()
function seems to do store the image for me, so that’s great. Only problem is, I don’t have anything to put into save_and_get_url()
, so I have no way to use it. I cannot BASE64
encode it because, it is not true file, yet. And there it is again.
@Sky Any ideas on how I should go about solving this?
Huh, what do you mean? The save_and_get_url()
function handles the image data, which in your case should work.