I use python with bottle framework. When the user clicks a button, the server should generate file and let the user download it. When the user downloads it completely, the server should delete this file.
Is there any way to achieve this?
I found the way by this page (flask solution) and this page(hooks plugin) and this page(Forced Download).
this is my solution:
put hook "after_request" function into route function
part of my code:
download page templete (only one button):
<form id="export" calss="etable" method="POST" action="/download">
<input type="submit" name="export" value="export">
</form>
download page
#route('/download')
def download():
output = template('download',template_lookup=['./views'])
return output
click button(generate file and redirect to download)
#route('/download',method = 'POST')
def downloadPost():
zipname = zipFolder('./temp') #create files
if zipname is not None:
return redirect('/download/'+zipname)
else:
abort(500,'error.')
Forced Download function (put hook in this part.)
#route('/download/<filename:path>')
def download_file(filename):
#hook('after_request')
def delFiles():
del('./temp/',filename) #delete file function
return static_file(filename, root='./temp/', download=filename)
Related
I am writing a tool to record and monitor downtime on a range of equipment.
I have my file structure as below:
File Structure
Sites is just a subfolder containing individual HTMLS for where the equipment is located.
Currently, flask runs webapp.py which contains:
>from . import app
>#app = (__init__.app)
>from . import views
>from . import ReportingTool
views.py has all of my #app.route's in it, up until the [site].html files. From there, on the [site].html file I ask for input from the user. I haven't started writing code to record the user input in any meaningful way, just want to get the data to a python script and commit them to variables. To this end, in the html file I have
<body>
<div class="menu">
<form method="post" enctype="multipart\form-data" action="{{ url_for('downTime') }}">
<fieldset class="datafieldset">
This then requests different data from the user in the form of multiple field sets as seen here: fieldsets
as you see in the code snippet above I set the action to be url_for('downTime'), downTime is a function in my python file ReportingTool.py. this throws out an error, "werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'downTime'. Did you mean 'supportguide' instead?" traceback
Is there something I need to add or specify on the html document to enable this page (and the other [site].html pages to call functions from the ReportingTool.py file? the #app.route that calls the [site].html file is this and that is called with a redirected from here I've only got it setup like that becuase I wanted the name for the site to appear in the address bar.
Thanks in advance.
I am not sure on steps to fix as I am kind of throwing myself in the deep end to learn basic coding by creating an application for my workplace to replace an excel spreadsheet I created.
You are not reaching the downTime function in the ReportingTool.py file. I suggest trying add_url_rule in your views.py by adding the /reported endpoint referencing the downTime function in ReportingTool.py. Something like this;
app.add_url_rule('/reported', 'ReportingTool.downTime', view_func=ReportingTool.downTime, methods=METHODS)
This answer is based on the responds for this question. You are trying to reach a function in a different file from your main view file. Assuming you are calling the page with the form from a function in the views.py file.
Solved with info from Kakedis' input, and the links they provided.
I added:
app.add_url_rule('/reported', 'ReportingTool.downTime', view_func=ReportingTool.downTime, methods=METHODS)
to webbapp.py, then:
#app.route('/reported')
def downTime():
try:
DTref = request.form['refDT']
except:
DTref = "No Reference"
print(DTref)
print("reported")
return(render_template("/UserRip.html"))
to ReportingTool.py
This now prints the above to console to confirm it's pulling the correct func and brings the user back to the starting page.
I have a trained model for speech synthesis. It creates audio correctly everytime from textarea in html page and saves it static folder. But sometimes when i return audio from folder it brings the older one. It doesnt happen everytime but i couldnt find solution.
html audio code
{% if my_audio %}
<audio controls>
<source src="{{ url_for('static', filename='a.wav') }}" type="audio/wav"/>
</audio>
{% endif %}
flask code if you needed
from flask import Flask, render_template, request
import inference
app = Flask(__name__)
app.static_folder = 'static'
#app.route("/")
def home():
return render_template("index.html")
#app.route("/sentez", methods = ["POST"])
def sentez():
if request.method == "POST":
metin = request.form["metin"]
created_audio = inference.create_model(metin)
return render_template("index.html", my_audio = created_audio)
if __name__ == "__main__":
app.run();
This issue arises due to the browser fetching the file from its cache instead of the static folder, after the first run. You need to append a parameter to to the audio file's URL (or query string) that would be unique, so that it will fetch a new copy from the static folder. I suggest appending number of milliseconds elapsed, getTime() method does this in JavaScript.
The JavaScript equivalent for changing the source is as follows:
function playAudio() {
var audioFile = new Audio('./a.wav');
//URL is ./a.wav
audioFile.play()
}
change this to
function playAudio() {
var audioFile = new Audio('./a.wav?' + new Date().getTime());
//URL becomes something like ./a.wav?1623483193060
audioFile.play()
}
You can find out how to do the same in Flask for modifying the statement
{{ url_for('static', filename='a.wav') }}
I am making a web app that generates a QR code using input from the user and saves it into a specified file. After the QR code is saved, It should display the generated QR code in a small box next to the input box.
I am attempting to do this by having a GET submit button that goes to this route but I receive an error every time I click it.
The first block of code is for receiving the input and making a QR code out of it, and the second is my attempt to send back the finished PNG and display it.
Python Code:
#app.route('/', methods= ['POST'])
def textfield():
text = request.form['text']
processed_text = text
if processed_text == '':
flash("Please enter a value!")
else:
QR(processed_text)
return render_template('base.html')
#app.route('/QR', methods= ['GET'])
def QRimage(text):
im = Image.open(f'{text}.png')
data = io.BytesIO()
im.save(data, "PNG")
encoded_img_data = base64.b64encode(data.getvalue())
img_data = encoded_img_data.decode('utf-8')
return render_template('base.html', value=img_data)
Here is the HTML to attempt to display the image:
<img id="picture" src="data:image/jpeg;base64,{{ img_data }}">
And the GET button that routes to /QR:
<form action="/QR" method="GET">
<button type="submit" type="button">QR Button</button>
Flask looks for static files in the static folder which is the default.
use flask.send_from_directory(directory, filename, **options) if you want to serve files from another directory. This is a secure way to quickly expose static files.
#app.route('/QR', methods= ['GET'])
def QRimage(text):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename);
Reference:
API — Flask Documentation (1.1.x) (2021). Available at: https://flask.palletsprojects.com/en/1.1.x/api/#flask.send_from_directory (Accessed: 24 April 2021).
Currently I am using flask and heroku to deploy my website but i need my webpage show random photo from img directory currently my code look like this
import os
import random
imgs = os.listdir('static/img')
imgs = ['img/' + file for file in imgs]
imgrand = random.sample(imgs,k=5)
#app.route('/')
def index():
return render_template('index.html', imgrand=imgrand)
And my HTML code look like this
{% for img in imgrand %}
<img src="static/{{img}}" alt="{{imgL}}" style="width:100%">
{% endfor %}
So long it work fine in my local machine ,but it only random picture only once when start flask run command in terminal. My goal is to make my web page random picture everytime when refresh webpage without going to end terminal session and start flask run command all over again.
In this case imggrand variable only takes one sample at the beggining of the program, for repeating the process everytime you refresh the webpage you need to put imggrand inside the endpoint.
I recommend you to learn about endpoints and designing the workflow starting with this: https://flask.palletsprojects.com/en/1.1.x/quickstart/#rendering-templates
I have created a web application, which allows its users to download files from the same server the application is running on. However, I can't make it work the way I want it to work, and now I'm not even sure if it's possible.
So, I have a form, which contains two user inputs and a "Download" button. The first user input lets you choose a file and the second user input lets you choose amount. When you hit the the download button, the application creates a zip file based on user input, and tries to send it to user. Anyway, the zip file is never sent to user.
Here's what the button looks like in html
<input type="submit" name="submit" value="Download" class="btn" >
And below is the send_file() function call in the application.
send_file(uploads + cfg_zipfile, attachment_filename=cfg_zipfile, as_attachment=True)
The function returns status 200, so it seems to be working. Still, no file is sent, but the file exists on the server. So, is this even possible to do it this way? I know I could create the zip file with the button, then a download link would appear and a user could download it from the link, but is it possible to get all this functionality with one button? Currently zip file's name also depends on user input (file chosen and amount).
I think you should create a service
<button ng-show='downloadReportview' data-toggle="modal" class="btn btn-success glyphicon glyphicon-download">
<a href="http://{{location}}/api/xx/xxxx//{{costDataReportName}}" download>Download Report</a>
</button>
This will call the service using GET method.
And the service in python will look smth like this :
def get(self, filename):
# RETURN THE INVOICE
file_name = str(expanduser("~")) + UPLOAD_PATH + str(filename)
f = open(file_name, "rb")
output = f.read()
self.set_header('Content-Disposition', 'attachment; filename=output.csv')
self.set_header('Content-type', 'text/csv')
self.write(output)
print("Invoice download")