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
I would like to use a class Track to have a function playsound() and this should play the sound on a html template.
This is my class :
class Track:
def __init__(self, name, path):
self.name = name
self.path = path
def playsound(self):
# does something
Now I know that I will need javascript and ajax as well probably. But I'm still new to the concept and I would like to see how I would go about achieving that. The sound file should play onload and should simply be invoked when you type:
songname = Track('name', 'music/filename.ogg')
#app.route('/playSong')
def playSong():
return songname.play()
If there is no way this can be done in this way, or there is a much better way, I'd be happy to be enlightened. Thanks in advance!
You can keep the src of in HTML as
<audio controls>
<source src="http://127.0.0.1:5000/a" type="audio/wav"/>
</audio>
where http://127.0.0.1:5000/a is the url which send_file the audio
python code :
#app.route('/a')
def returnAudioFile():
path_to_audio_file = pwd+"\\question_folder\\audio.wav" #audio from project dir
return send_file(
path_to_audio_file,
mimetype="audio/wav",
as_attachment=True,
attachment_filename="test.wav")
If I understood the question correctly, you should put an <audio> HTML element in your template and go from there. Flask will only serve the rendered template, it can't play the sound directly.
This question already has an answer here:
Can't play HTML5 video using Flask
(1 answer)
Closed 7 years ago.
I have a simple flask server. I downloaded, using pafy, a video from a youtube link provided by the user.
#app.route('/')
def download():
return render_template('basic.html')
The basic.html template has a form that submits an action to download:
<form action="download_vid" method="post">
Link: <input type="text" name="download_path"><br>
<input type="submit" value="Submit">
</form>
I have another end point, /download_vid that looks like this.
#app.route('/download_vid', methods=['POST'])
def download_vid():
url = request.form['download_path']
v = pafy.new(url)
s = v.allstreams[len(v.allstreams)-1]
filename = s.download("static/test.mp4")
return redirect(url_for('done'))
The desired link is indeed downloaded as a .mp4 file in my static folder. I can watch it and I can also use it as a source for a tag in an HTML file, if I open it locally.
#app.route('/done')
def done():
return app.send_static_file('test.mp4')
From what I understand, 'send_static_file' serves files from the static directory. However, I get a 404 error when I run the server, even though the video is clearly there.
I have also tried a different version for done():
#app.route('/done')
def done():
return return render_template('vid.html')
Here, vid.html resides in templates and has a hard coded path to static/test.mp4. It is loaded after the download is complete. I do not have a 404 error in this case, but the tag don't do anything, it's just gray. If I open vid.html locally (double click on it), it works, it shows the video.
Can you please help me understand what is going on?
What I want to achieve is this:
Take an input from the user [ Done ]
Use that input to download a video [ Done ]
Serve that video back to the user [ ??? ]
I think you have something going on with file paths or file permissions.
Is the video being downloaded into static directory?
Is the static directory in the same directory, along with your main.py file?
Does your flask app have permissions to read the file?
I think the reason your file did not load in html template is because you referenced it as static/test.mp4 from an url - /done which translates the video path to be /done/static/test.mp4.
Instead of trying to push the file using Flask, you can redirect to the actual media file.
#app.route('/done')
def done():
return redirect('/static/test.mp4')
I'm looking to use Flask to host a single-page website that would allow users to upload a CSV that would be parsed and put into a database. All of the database shenanigans are complete (through SQLalchemy in another Python script) and I've got everything worked out once a script has access to the CSV, I just need help getting it there.
Here's the scenario:
1. User directs browser at URL (probably something like
http://xxx.xxx.xxx.xxx/upload/)
2. User chooses CSV to upload
3. User presses upload
4. File is uploaded and processed, but user is sent to a thank you page while our
script is still working on the CSV (so that their disconnect doesn't cause the
script to abort).
It's totally cool if the CSV is left on the server (in fact, it's probably preferred since we'd have a backup in case processing went awry)
I think what I want is a daemon that listens on a socket, but I'm not really experienced with this and don't know where to start getting it configured or setting up Flask.
If you think some framework other than Flask would be easier, definitely let me know, I'm not tied to Flask, I've just read that it's pretty easy to set up!
Thank you very much!!
Here is a (very slightly simplified) example of handling file uploading in web.py based on a cook book example (the Flash example, which I have less experience with, looks even easier):
import web
urls = ('/', 'Upload')
class Upload:
def GET(self):
web.header("Content-Type","text/html; charset=utf-8")
return """
<form method="POST" enctype="multipart/form-data" action="">
<input type="file" name="myfile" />
<br/>
<input type="submit" />
"""
def POST(self):
x = web.input(myfile={})
filedir = '/uploads' # change this to the directory you want to store the file in.
if 'myfile' in x: # to check if the file-object is created
filepath=x.myfile.filename.replace('\\','/') # replaces the windows-style slashes with linux ones.
filename=filepath.split('/')[-1] # splits the and chooses the last part (the filename with extension)
fout = open(filedir +'/'+ filename,'wb') # creates the file where the uploaded file should be stored
fout.write(x.myfile.file.read()) # writes the uploaded file to the newly created file.
fout.close() # closes the file, upload complete.
raise web.seeother('/')
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
This renders a upload form, and then (on POST) reads the uploaded file and saves it to a designated path.
I am a behavorial scientist and usually collect data by letting participants do some tasks on a computer and record their responses (I write the programs using the pyglet wrapper PsychoPy). That is, the program runs locally and the data is stored locally.
Now I would like to know if there is a way to use Python to display a (local) website with html-forms to the user and collect the input (locally). The reason for this idea is that currently whenever I want to display checkboxes, radiobuttons, or input fields I use wxPython. This works quite well, but programming and layouting in wxPython is kind of cumbersome and I would prefer html with forms.
A requirement would be that it would need to rum without any borders, adress field, menu bar, ... The reason is that I need it in kind of fullscreen mode (I currently open a non-fullscreen pygflet window in the size of the screen to hide the desktop) so that participants can do nothing but work on the forms.
So I am looking for a way to (a) display html websites including html form above a pyglet window with no menu bar or whatsoever, (b) collect the input when clicking on the Ok button (i.e., the form is send), (c) control what is presented prior and after viewing this website, and (d) everything of this should happen locally!
My idea would be that the data is collected when participants hit the "Send away" button in the following example pic and the next page is displayed.
Update: I use windows (XP or 7).
This is a solution using Qt Webkit for rendering HTML. The default navigation request handler is wrapped by a function that checks for submitted form requests. The form uses the "get" method, so the data is included in the url of the request and can be retrieved that way. The original request is declined and you can change the content of the displayed web page as you wish.
from PyQt4 import QtGui, QtWebKit
app = QtGui.QApplication([])
view = QtWebKit.QWebView()
# intercept form submits
class MyWebPage(QtWebKit.QWebPage):
def acceptNavigationRequest(self, frame, req, nav_type):
if nav_type == QtWebKit.QWebPage.NavigationTypeFormSubmitted:
text = "<br/>\n".join(["%s: %s" % pair for pair in req.url().queryItems()])
view.setHtml(text)
return False
else:
return super(MyWebPage, self).acceptNavigationRequest(frame, req, nav_type)
view.setPage(MyWebPage())
# setup the html form
html = """
<form action="" method="get">
Like it?
<input type="radio" name="like" value="yes"/> Yes
<input type="radio" name="like" value="no" /> No
<br/><input type="text" name="text" value="Hello" />
<input type="submit" name="submit" value="Send"/>
</form>
"""
view.setHtml(html)
# run the application
view.show()
app.exec_()
As AdamKG mentioned, using a webframework would be a good choice. Since Django and similar might be an overkill here, using a micro webframework like 'flask' or 'bottle' would be a great choice.
This link demonstrates via step by step instruction how to make a simple form via a To-DO application. It assumes zero previous knowledge.
You can run it only locally also.
your want a simple solution, so just write a http server and run your simple page.
using python.BaseHTTPServer, coding a 15 line web server:
import BaseHTTPServer
class WebRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
if self.path == '/foo':
self.send_response(200)
self.do_something()
else:
self.send_error(404)
def do_something(self):
print 'hello world'
server = BaseHTTPServer.HTTPServer(('',80), WebRequestHandler)
server.serve_forever()
easy enough,but i suggest using some web frameworks. They are easy too.
for example, web.py. here is what u want in 50 line codes:
install web.py
make a dir with 2 files:
./
|-- app.py
`-- templates
`-- index.html
index.html
$def with (form, ret)
<html>
<head>
<title> another site </title>
</head>
<body>
<h1> hello, this is a web.py page </h1>
<form action="" method="post">
$:form.render()
</form>
<h2>$:ret</h2>
</body>
</html>
app.py logic file:
import web
### Url mappings
urls = (
'/', 'Index', )
### Templates
render = web.template.render('templates')
class Index:
form = web.form.Form(
web.form.Textbox('fav_name', web.form.notnull, description="Favorite Name:"),
web.form.Textbox('cur_name', web.form.notnull, description="Current Name:"),
web.form.Button('Send Away'),
)
def GET(self):
""" Show page """
form = self.form()
return render.index(form, "")
def POST(self):
""" handle button clicked """
form = self.form()
if not form.validates():
return render.index(form, "INPUT ERROR")
# save data by ur method, or do some task
#pyglet.save_data(form.d.fav_name, form.d.cur_name)
#pyglet.draw(some_pic)
#os.system(some_cmd)
form = self.form()
return render.index(form, "YOUR DATA SAVED")
app = web.application(urls, globals())
if __name__ == '__main__':
app.run()
run this server in your windows:
python app.py 9999
open browser: http://127.0.0.1:9999/
by the way, if ur data is only strings, u can save them in web.by by sqlite.
My suggestion would be:
Use some python server as, for example SimpleHTTPServer. It is needed because the submit button on forms sends the information to a server. There you should manage the received info some way;
Have your browser configured with one of those Kiosk extensions, which disallow even the use of Alt+F4. An example would be Open Kiosk extension for Firefox
Optionally, if you have affinity with scripts in general, you could create a script which, when executed, would at the same time run the python server AND open your html file in the browser. That would ease a lot your setup work for every subject in your group.
EDIT: I've read you need the pyglet over the browser window. That could be included in the script of step 3, using "always on top" option and absolute positioning of the pyglet (I can tell this would probably be simpler on Linux, which could be run from persistent LiveUSB - just a thought!)
EDIT (regarding the posted comment):
I think the most reliable option for output would be to disk (file or database) instead or RAM (running python object), then you read the info from file afterwards. Then, in case of a surprise (system hang, power failure), the already-entered data would be there.
The only (and most important) part I don't know HOW to do is to handle the content of the form's "submit" on the server-side. Probably some server-side script file (php, python) shoud be created and left on the server root, so the server would receive an http request containing the info, and send the info to the script, which then handles the processing and file/database storage activities.
This might be of your interest:
"The POST request method is used when the client needs to send data to the server as part of the request, such as when uploading a file or submitting a completed form." (from wikipedia on "POST(HTTP)" ENTRY)
In another link, some thoughts on using SimpleHTTPServer itself for handling POST requests:
http://islascruz.org/html/index.php/blog/show/Python%3A-Simple-HTTP-Server-on-python..html
Hope this helps.
The reason for this idea is that currently whenever I want to display
checkboxes, radiobuttons, or input fields I use wxPython. This works
quite well, but programming and layouting in wxPython is kind of
cumbersome and I would prefer html with forms.
You can combine the ease of HTML and still create native Windows applications using Flex with a Python backend.
If you are averse to Flex, a bit more - involved - but still native windows application generator is Camelot
Edit
Instead of typing it out again - I would suggest the django + flex + pyamf article on Adobe that explains it all with screenshots as well. You can replace django with flask or bottle as they are more lightweight, however the PyAMF library provides native support for django which is why it was used in the example.
PyAMF provides Action Message Format (a binary protocol to exchange object with the flash runtime) support for Python.