Python Flask, downloading a file from server - python

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")

Related

flask.request.form Cached Data

I've written an app that contains an html text input:
<form method="POST" action="" enctype="multipart/form-data">
<input class="ocsp_override_box_input" type="text" id="ocsp_override" name="ocsp_override" placeholder="Override the AIA field with a URL here..." value="">
</form>
In the flask app, I access the data with the following:
ocsp_override = request.form.get('ocsp_override')
It works as expected and the rest of my code is able to use this string value and do things with it. So far, so good. The way the code works is that this field should be optional. If it is blank, then it is ignored. If data is filled in it, it runs some checks and then uses this override string later on.
The issue I'm finding is that if I complete the text form using flask dev, it works as expected, but when I reload the page and leave it blank, it appears to be caching the previous entry.
For instance, if I enter in http://example.com in the text field, the code will use that string. If I reload the page (not using F5, by reloading the get page so I can post again), and I leave the field blank, the code appears to be trying to use http://example.com again. What's weird is that if I try to print(request.form.get('ocsp_override')) then it shows nothing.
If I wait a length of time (I want to say 10 mins), and then try again, everything works as expected with the field blank.
Is there some kind of caching happening here and how can I force it to reload and be fresh every time?
You might try disabling autocomplete:
e.g.
<input class="ocsp_override_box_input" ... autocomplete="off">
And if that does not work, you can try adding a cache control header to the response to prevent the browser from caching the page:
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
response.headers['Pragma'] = 'no-cache'
response.headers['Expires'] = '0'
return response
See this answer describing Cache-Control vs Pragma headers.

Calling a function on HTML page, not found

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.

Storage data from HTML Form as a variable and print it in the html table (Python Flask?) [duplicate]

This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Get the data received in a Flask request
(23 answers)
Closed 2 years ago.
So here's what i'm trying to do:
Static Website in HTML(just a simple table) Screenshot Here
Admin Page to update text's on that website by html for (I'm not sure if it's good idea) Another Screenshot
I was trying in Python Flask, but I have no idea how to storage data from HTML Form into Python variables. All I did is to use {{ }} in my index.html(first ss) and then I can edit content straight from Python Code, but it's not what I want.
What i want?
I want to make a form or smth like that which allows user to easy update text on index(first ss).
User has to choose which cell he wants to update and write a new content, then submit and that's all.
Is it Python Flask good idea to do it? (I'm pretty new in Python)
At the moment I'm using Wordpress+PostGrid plugin to do something like that, but editing the grid(first ss) is there so hard.
I'm stubborn that's why I want to do it on my self.
Any advises about method which I should use or language will be very helpful.
Thanks!
Since you do NOT want to render a template of your table website, but change the HTML file itself, I have the following proposition for you:
Set up a Flask application to receive your request, e.g. on an update route (/update).
Have your admin website use a form that posts to your update route. Make sure to give your select and input tags the name attribute. For example:
<form action="{{url_for('update')}}" method="post">
<select name="element">
<option value="imptitle">imptitle</option>
<option value="zaktitle">zaktitle</option>
</select>
<input type="text" name="new_value">
<input type="submit" value="Update">
</form>
In your Flask app you can extract the information from the request by using request.form, using the same names that you specified in your select and input tags, e.g.:
#app.route('/update', methods=['POST'])
def update():
element = request.form['element']
new_value = request.form['new_value']
Then replace the element's value within your table HTML: open your table HTML file, read its content, search the element and replace its value using regular expression (you can read up on how to do that here), overwrite the contents of the file with updated content. For example:
with open('index.html', 'r') as f:
content = f.read()
# new_content = ... (do your search and replace here)
with open('index.html', 'w') as f:
f.write(new_content)

How to delete file after user download with bottle framework...?

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)

Reading and writing files from html in Google App Engine

I am working with GAE and Python, I know python, but I don't know HTML, which seems to be what I need right now. I want to take in a text file write something in it then return it for download. I am using other people's examples, but far all I have is:
class MainPage(webapp.RequestHandler):
#http://bukhantsov.org/2011/12/python-google-app-engine-calculator/
def get(self):
self.response.out.write("""<html>
<body>
<form action='/' method='get' autocomplete='off'>
<input type='file' name='file'/><br/>
</form>
</body>
</html>""")
I imagine there is something I need to put in the file line so I can access what the user feeds it, but I don't know what or how to access it from the python code. So what should I do here?
If I understand your question correctly, you are trying to grab the text data being sent by the user via the GET call that is defined by the form action HTML line.
Concisely, you are looking for this call:
file = self.request.get('file')
This may also be useful:
filename = self.request.GET['file'].filename
These can be used in the same location and in conjunction with your "self.response.out".
More information can be found here:
https://developers.google.com/appengine/docs/python/tools/webapp/requestclass#Request_get
Alternatively, the BlobStore APIs may be easier.
https://developers.google.com/appengine/docs/python/blobstore/overview
Possibly related:
Upload files in Google App Engine,
Get original filename google app engine
Hope that helps!
Jess

Categories

Resources