Hi all, im a bit new in Python.
So I have a confused issue for me. I need to store image in database, and after that I have to display each image on client side. Im using Flask for rest request.
So here I have my simpl marckup for submitind
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="image">Select image</label>
<input type="file" name='img' id='image'>
<input type="submit" id='upload_img'>
</form>
and here I get my request and save it to my DB
#app.route("/upload", methods=["POST"])
def upload_image():
# get current image file
img_file = request.files['img']
# get Content Type and File Name of current image
content_type = img_file.content_type
filename = img_file.filename
# save to GridFS my image
# fields <-- recive the id of just saved image
fields = db.FS.put(img_file, content_type=content_type, filename=filename)
# store the filename and _id to another database
# so here we can much morea easaly get image from our GridFS
db.Mongo['images'].insert({"filename": filename, "fields": fields})
return index(images=[])
My simple database model
class db(object):
URI = "mongodb://localhost:27017"
Mongo = None
FS = None
#staticmethod
def initialize():
client = pymongo.MongoClient(db.URI)
db.Mongo= client['gallery']
db.FS = GridFS(Database.DATABASE)
And all saves is successfully.
Retrive my image from DB and try to send it on clietn
#app.route('/get_all_images')
def get_image():
images = db.Mongo['gallery'].find({})
# try to get just a first image _id and fing it at GridFS files
image = db.FS.get(images[0]["fields"])
#send to the client
return index(images=image.read())
Here is markup for display image from the response
<div>
<img src="data:image/png;base64,{{images}}" alt="">
<div>{{images}}</div>
</div>
and finnaly I get something like this enter image description here
the response is look like this:
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00w\x00\x00\x00\x7f\x08\x06\x00\x00\x00\xd5j]\xe7\x00\x00\x00\x19tEXtSoftware\x00Adobe ImageReadyq\xc9e<\x00\x00\x03"iTXtXML:com.adobe.xmp\x00\x00\x00\x00\x00
The problam is that I cant figute out how to convert this byte format into real image..and display it on a web page directly from database.
I try to make several variants to solve this problam..but in some how my mind is blow up..and I really dont undestand how to work with it.
Thanks for your time :)
IF somebady have any idias or advice how can I show images from database into client side...
I did it! :)
I figured out how to fix this by myself.
Actually the problem was in my response...and in some case on client side too.
Because when I send request from the server, I send the data in byte format,
print(type(image.read()))
<class 'bytes'>
while at the client I suggested the something like binary string
<img src="data:image/png;base64,{{images}}" alt="">
There is my solution code:
import codecs
base64_data = codecs.encode(image.read(), 'base64')
image = base64_data.decode('utf-8')
And on the client I receive the string, which I paste into the img tag...and taddaaaa I got image from my database.
Thanks all who try to help me or figure out how to fix my issue.
I'm not sure that is the best practice, but it works.
P.S. sorry for my English :P
Related
So I send a Form to my Flask App and wish to receive the Form image data input and pass it to another function.
Example of form:
<form action="https://example.com/api/accept_form" method="POST" enctype="multipart/form-data">
<label for="fileupload"><input type="file" name="fileupload" value="fileupload" id="fileupload" accept="image/*">
Select a file to upload</label>
<br><button id="submit">Post to Instagram</button>
</form>
On the flask app:
def image_function(image):
#DO SOMETHING WITH THE IMAGE
#main.route("/api/accept_form", methods=["POST"])
def manipulate_image():
image = request.form["fileupload"]
image_function(image)
I can see how the image data looks using the print command:
request.files["fileupload"] = <FileStorage: '666650673.jpg' ('image/jpeg')>
request.files["fileupload"].read() = b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x00\xff\xe1\x00 and so on ...'
How do I pass the image to another function in the Flask App as if it was the original .jpg submitted, called from the Flask Apps current directory using "./666650673.jpg"?
References:
https://linuxhint.com/python-string-decode-method/
https://stackoverflow.com/a/2324133/14843373
https://github.com/williballenthin/python-evtx/issues/43
My mistake, as #teddybearsuicide pointed out was that I was passing a file handle and not a file pointer.
Maybe there is a better way but I just saved it locally on the EC2 based on this
Solution
request.files["image"].save("./imageToSave.jpg")
And called it as you would any file in your directory.
image = "./imageToSave.jpg"
I would prefer not to have had to save it so if anyone knows how to pass the file handle directly to achieve the same effect that would be great.
I've created a python script that loads an excel file up from my computer and, after working with the information inside it using openpyxl, saves a new excel file. The script works on my computer. For longevity purposes, I want to make the script into a website, using pythonanywhere or something similar to it (incorporating flask seemed like the best way to convert my script into a website). However, I am having trouble finding a way to accept a file from the user, as I have very little experience using flask. Here's the code I currently have that creates a "choose file" button and a "process file" button:
app = Flask(__name__)
app.config["DEBUG"] = True
#app.route("/", methods=["GET", "POST"])
def file_summer_page():
if request.method == ("POST"):
input_file = request.files["input_file"]
wb_master = load_workbook(input_file)
output_data = main(wb_master)
response = make_response(output_data)
response.headers["Content-Disposition"] = "attachment; filename=result.csv"
return response
return '''
<html>
<body>
<p>Load up the automated eval that MS Forms gives you:</p>
<form method="post" action="." enctype="multipart/form-data">
<p><input type="file" name="input_file" /></p>
<p><input type="submit" value="Process the file" /></p>
</form>
</body>
</html>
'''
Bear with me. Again, I haven't used Flask much, but this is my idea so far. Main(wb_master) essentially calls the script I made, so that it could hopefully run. At the moment, this returns the following error: "AttributeError: 'SpooledTemporaryFile' object has no attribute 'seekable'." In this case, I don't really know what it means, but I assume it is due to the fact that I am not reading the file correctly. Any help would be greatly appreciated!
I'm trying just for learning how to serve a video with the blobstore without it takes all the screen the video, for example
here I imported Video as video_model
class ViewVideo(webapp.Reque...,blobstore_handlers.BlobstoreDownloadHandler):
def get(self):
video_id = self.request.get('video_id')
video_instance = None
if video_id:
video_instance = video_model().get_video_content(video_id)
self.response.headers['Content-Type'] = 'video/mp4'
self.send_blob(video_instance.content.key())
class Video(db.Model):
content = blobstore.BlobReferenceProperty()
title = db.StringProperty()
def get_video(self,video_id):
return Video.get_by_id(video_id)
def get_video_content(self,content):
query_str = "SELECT * FROM Video WHERE content =:content"
return db.GqlQuery(query_str,content=content).get()
Where the video_id came from a url given, but as you see I put it directly in send_blob() function and this one when I tested it takes all the screen just to see the video, I was wondering how can I serve the video from my application without happening this, I was thinking embedded HTML but I can't figure it out how the source will be
Any help will be grateful
If it lacks of content to answer the question I will edit it
Without HTML5, it's a tricky mess. With HTML5, it becomes easy & elegant. Serve to the user's browser, as part of whatever page you're serving, the following HTML (5) snippet:
<video width="320" height="240" controls>
<source src="/getmp4?video_id=whatever" type="video/mp4">
Your browser does not support the video tag: please upgrade it!
</video>
and use that ViewVideo handler to serve only the /getmp4 URL, not the URL that your user directly gets via their browser.
The 320, 240, and the choice to show controls, are all optional, of course -- as even more is the use of whatever for the video id!-)
I need to upload and process a CSV file from a form in a Google App Engine application based on Webapp2 (Python) I understand I could use blobstore to temporary store the file but I am curious to know if there is a way to process the file without having to store it at all.
If you need to upload a file via webapp2 with an HTML form, the first thing you need to do is change HTML form enctype attribute to multipart/form-data, so the code snippet seems like:
<form action="/emails" class="form-horizontal" enctype="multipart/form-data" method="post">
<input multiple id="file" name="attachments" type="file">
</form>
In python code, you can read the file directly via request.POST, here's a sample code snippet:
class UploadHandler(BaseHandler):
def post(self):
attachments = self.request.POST.getall('attachments')
_attachments = [{'content': f.file.read(),
'filename': f.filename} for f in attachments]
The content of uploaded files is in self.request.POST in your handler, so you can get that content (assuming e.g the field for the uploaded file is named 'foo') with e.g
content = self.request.POST.multi['foo'].file.read()
So now you have the content as a string -- process it as you wish. This does of course assume the thing will fit in memory (no multi-megabyte uploads!-)...
Ok, I have managed to create a flask page that shows a bokeh image -- now I have to somehow put that into a template
https://gist.github.com/cloudformdesign/a0c5f2e8558ea3b60f0a
What I would like is to create a webpage with a few text boxes where the user can type the data they want to graph and it will be graphed below the text boxes. The user can select new data they want graphed and the graph will update.
I am very bad at coding in html, so I am very bad in creating templates. How would I do something like this?
I created my own example, thanks to #elyase
https://github.com/bokeh/bokeh/tree/master/examples/embed/simple
This is a very simple example of embedding bokeh pages in an html page. The example giving by #elyase was helpful, but didn't actually work with python3 (I could not import or install pyaudio). It was also overly complicated for what I was trying to ask. The gist above gives a very simple answer with only two files, all in the same directory. Thanks a ton!
Basically you need to create a view which will serve as static image, and you get the image url from that route.
I haven't got your included library so I'm going to use matplotlib and numpy to simulate what you are trying to attempt. This isn't a FULL solution for you (it's in the simplest working way using 2 views and 1 simple template), but you should be able to understand all the ESSENTIAL techniques which let you finish off your page.
I have a few comments and guidelines, and I think the code itself is pretty much self explanatory.
OK, here is the view main.py:
from flask import Flask, render_template, request, send_file
import matplotlib.pyplot as plt
import numpy as np
from StringIO import StringIO
app = Flask(__name__)
#app.route('/plot/')
def plot():
try:
# try to get the query string like ?width=xxx&height=xxx
height = int(request.args.get('height'))
width = int(request.args.get('width'))
except ValueError:
# if height, width not available, set a default value
height, width = 100, 100
# I randomly generate the plot which just based on H x W
# you should be able to generate yours from your library
to_draw = np.random.randint(0, 255, (height, width))
img = plt.imshow(to_draw)
# you can convert the graph to arrays and save to memory
imgIO = StringIO()
img.write_png(imgIO, noscale=True) # save to memory
imgIO.seek(0)
# and send that image as file as static file of url
# like... /plot/?width=100&height=100
return send_file(imgIO, mimetype='image/png')
# this is the main page with the form and user input
#app.route('/', methods=['GET', 'POST'])
def index():
# set the default values
height, width = 100, 100
# handle whenever user make a form POST (click the Plot button)
if request.method == 'POST':
try:
# use this to get the values of user input from the form
height = int(request.form['height'])
width = int(request.form['width'])
except ValueError:
pass
# and pass the context back to the template
# if no form is POST, default values will be sent to template
return render_template('index.html', height=height, width=width)
if __name__ == '__main__':
app.debug = True
app.run()
And the template at templates/index.html:
<html>
<head>
<title>Micro Plot!</title>
</head>
<body>
<h1>Interactive Plot</h1>
<form action="/" name="plot" method="POST">
<p><input type="text" name='height' value="{{ height }}" /></p>
<p><input type="text" name='width' value="{{ width }}" /></p>
<p><input type="submit" value="Plot Now!"></p>
</form>
<img src="{{ url_for('plot', height=height, width=width) }}" />
</body>
</html>
The trick is to set the image src to send a GET request to the url, and then Flask's /plot/ view to render an in-memory image and feed back as static.
Key Notes:
The url_for will then dynamically generate the src as like /plot/?width=xxx&height=xxx.
To get the querystring from the url in the view, use request.args.get('KeyName').
Once your plot is ready, save it in the memory with Python StringIO module and use Flask's send_file to serve as static content.
You should read and learn more about Flask and HTML, you cannot build something really amazing without having a good understanding of how these things work together.
I hope this helps you understand the underlying techniques, and Good Luck!
I ended up creating my own answer with the help of elyase, and the code was pulled into an example folder in the bokeh project. Check it out here:
https://github.com/bokeh/bokeh/tree/master/examples/embed/simple