Flask / Python: Modify uploaded file data before saving - python

I would like to be able to upload a csv file, then have a script in python do some modifications to the file, and finally save the file after changes to a specific folder. I have something like this, but I don't know why it doesn't work:
import os
from flask import Flask, render_template, request, redirect, url_for, send_from_directory
from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_FOLDER = 'C:/Users/tkp/Desktop/uploads_files'
app.config['UPLOAD_EXTENSIONS'] = ['.csv']
app.config['UPLOAD_PATH'] = UPLOAD_FOLDER
#app.route('/')
def index():
files = os.listdir(app.config['UPLOAD_PATH'])
return render_template('index.html', files=files)
#app.route('/', methods=['POST'])
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
uploaded_file.stream.seek(0)
f = uploaded_file.read()
#some change in the file
f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('index'))
#app.route('/Users/tkp/Desktop/uploads_files/<filename>')
def upload(filename):
return send_from_directory(app.config['UPLOAD_PATH'], filename)
And HTML file:
<!doctype html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="POST" action="" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Convert"></p>
</form>
<hr>
</body>
</html>
Is it possible to perform such an operation on the fly or do you have to save the uploaded file first?

You are doing everything correctly, except the f.save(...) definition.
When you do f = uploaded_file.read(), the f is the result of the .read() operation, which is bytes, not a file.
You have to open another file and save the contents to it.
Don't forget to .decode() the bytes, to make it a string.
Here's a working snippet:
#app.route('/', methods=['POST'])
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
uploaded_file.stream.seek(0)
f = uploaded_file.read().decode()
# WE don't want any failures
f = f.replace("FAIL", "SUCCESS")
filename_to_save = os.path.join(app.config['UPLOAD_PATH'], filename)
with open(filename_to_save, "w") as file_to_save:
file_to_save.write(f)
return {"status": "OK"}

It could probably be a typo in your action attribute. Change this line:
<form method="POST" action="" enctype="multipart/form-data">
to this:
<form method="POST" action="/" enctype="multipart/form-data">

Related

Upload multiple files using flask and read as variable

I have a python script that reads content of 2 files, and maps the data and outputs a csv. Currently the code reads the path of the files however I want it so that the user uploads the file and the code reads the files and generates the csv.
I started the flask code that uploads the multiple files but I need help saving the files to variables that my python script would be able to read.
My python script:
user_input = input("Enter the path of First File : ")
user_input2 = input("Enter the path of Second File : ")
assert os.path.exists(user_input), "Invalid file at, " + str(user_input)
f = open(user_input, 'r')
f2 = open(user_input2, 'r')
content = f.read()
content2 = f2.read()
def parse_value(txt):
reclines = []
for line in txt.split('\n'):
if ':' not in line:
if reclines:
yield reclines
reclines = []
else:
reclines.append(line)
def parse_fields(reclines):
res = {}
for line in reclines:
key, val = line.strip().rstrip(',').split(':', 1)
res[key.strip()] = val.strip()
return res
res = []
for rec in parse_value(content):
res.append(parse_fields(rec))
res2 = []
for rec in parse_value(content2):
res2.append(parse_fields(rec))
df = pd.json_normalize(res)
df2 = pd.json_normalize(res2)
flask codes for uploading files:
upload.py
import os
import magic
from app import app
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
ALLOWED_EXTENSIONS = set(['tpi'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('button.html')
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
print(request.__dict__)
# check if the post request has the file part
if 'sfile' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['sfile']
if file.filename == '':
flash('No file selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are tpi')
return redirect(request.url)
if __name__ == "__main__":
app.run(host="0.0.0.0", port = 5000, debug=True)
button.html
<!doctype html>
<title>Python Flask File Upload Example</title>
<h2>Upload First File</h2>
<form method="post" name="sform" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="sfile" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" name="ssubmit" value="Submit">
</p>
</form>
<h2>Upload Second File</h2>
<form method="post" name="wform" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="sfile" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" name="wsubmit" value="Submit">
</p>
</form>
How can I fix the flask codes to save the first uploaded file to variable f and and second uploaded variable to f2?
What you're looking for is the .read() method.
with open(user_input, 'r') as file:
file_one = file.read()
with open(user_input, 'r') as file:
file_two = file.read()
You may need to instantiate the file vars outside the context manager, but something like this should get you started

How can I enable the user to post a music file in their post using Flask?

My site will enable users to post something like a blog post, but with a audio file attached to it, so that other user can listen to it while reading. I made a dummy post so that I could check a few things and also a simple route.
from flask import render_template
from site import app
posts = [{
'title': 'asdf',
'text': 'asdf',
'file': "2.mp3"
}]
#app.route("/")
#app.route("/home")
def home():
return render_template('home.html', posts=posts)
I also have the home.html template
<!DOCTYPE html>
<html>
<head>
<title>Site</title>
</head>
<body>
{% for post in posts %}
<h1>
{{ post.title }}
</h1>
<h2>
{{ post.text }}
</h2>
<audio controls>
<source src="{{ post.file }}" type="audio/mpeg">
</audio>
{% endfor %}
</body>
</html>
My logic was simple: if the 2.mp3 file is in the same directory as the home.html file, then the music should play. But it doesn't. I don't really have an idea what should I do. I'm using Python 3.7.
This is actually a bit more complex than that because they're is two options.
The first is the "easy one" and what's you're trying to achieve. Having the file in the static folder along with the home template and return it to the user via the template.
To achieve that, you just need to modify your template a bit:
<source src="{{ url_for('static', filename=post.file) }}" type="audio/mpeg">
However, that will not work if the file is not in your static folder (i.e. if the user uploads the file himself).
For that, you will need to follow the steps in the docs and you will probably end up to something close to the following:
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
from flask import send_from_directory
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', '.mp3'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)

How to read single file in my data using Flask

I'm new in Flask, I want to take single file that have been uploaded in my upload path. Then i want to read and send it to my html after hr tag. How can i do that?
This is My Code:
import os
from flask import Flask, render_template, request, redirect, url_for, abort, \
send_from_directory
from werkzeug.utils import secure_filename
app = Flask(__name__)
app.config['UPLOAD_EXTENSIONS'] = ['.txt', '.doc']
app.config['UPLOAD_PATH'] = 'uploads'
#app.route('/')
def home():
files = os.listdir(app.config['UPLOAD_PATH'])
return render_template('home.html', content=files)
#app.route('/', methods=['POST'])
def upload_file():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
file_ext = os.path.splitext(filename)[1]
if file_ext not in app.config['UPLOAD_EXTENSIONS']:
abort(400)
uploaded_file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('home'))
if __name__ == "__main__":
app.run()
And This one is my HTML Page:
<!doctype html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="POST" action="" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Submit"></p>
</form>
<hr>
{{ content }}
</body>
</html>
It saves the data, but I can't access the data since I use this codefiles = os.listdir(app.config['UPLOAD_PATH'])
You need a variable route that will accept the a filename like #app.route('/<filename:filename>').
You then need to get the file with that name from your upload directory like file_path = os.path.join('UPLOAD_PATH', filename).
Then you need to read the contents of that file and pass it into your view.
with open(file_path) as file:
content = file.read()
Then you can access it in your HTML file and display it.
<p>{{ content }}</p>
Here is a complete example of the route I described:
#app.route('/<filename:filename>')
def display_file(filename):
file_path = os.path.join('UPLOAD_PATH', filename)
with open(file_path) as file:
content = file.read()
return render_template('display_file.html', content=content)

Render image from gridfs on html page using flask

I want to render an image from gridfs on my html pyge using flask.
I store the image in my mongodb using gridfs with one button and also store the ObjectId of the image in a serverside session using Flask-Session.
When I click on another button, I get the correct ObjectId of the image stored before via my session and then want to render this image from gridfs in my html page, but I don't know how to do it.
My app.py file:
from flask import Flask, render_template, request, redirect, session
from werkzeug.utils import secure_filename
from pymongo import MongoClient
from gridfs import GridFS
from flask_session import Session
DB = 'test-grid'
COLLECT = 'test-session'
client = MongoClient('mongodb://127.0.0.1:27017')
db = client[DB]
fs = GridFS(db)
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16*1024*1024
app.config['SESSION_TYPE'] = 'mongodb'
app.config['SESSION_MONGODB'] = client
app.config['SESSION_MONGODB_DB'] = DB
app.config['SESSION_MONGODB_COLLECT'] = COLLECT
Session(app)
#app.route("/")
def home():
return render_template("index.html")
#app.route('/upload', methods=['POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file']
filename = secure_filename(f.filename)
f_id = fs.put(f, filename=filename)
session['f_id'] = f_id
session['filename'] = filename
return redirect('/')
#app.route('/display', methods=['GET'])
def display_file():
if request.method == 'GET':
f = fs.get(session['f_id'])
image = f.read()
return render_template("index.html", user_image=image)
if __name__ == "__main__":
app.run(debug=True)
My index.html file:
<html lang='en'>
<head>
<meta charset='UTF-8'/>
</head>
<body>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" onchange="this.form.submit()" name="file" autocomplete="off" required>
</form>
<form method="get" action="/display">
<input type="submit" value="Display">
</form>
<img src="{{ user_image }}" alt="Show image here"/>
</body>
</html>
My requirements.txt file:
Flask
Flask-Session
pymongo
But this doesn't work and I get the following output:
Output
Can someone please help me fix this? Maybe with examples I can look up.

Flask Upload File Not Found

I want to make a file uploader using Python, Flask, and HTML. If I upload a file I get:
Not Found
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
import os
from flask import Flask, request, redirect, url_for, render_template
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = './user/Tom/Files/'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == ['POST']:
if 'file' not in request.files:
flash('Geen Bestand')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('Geen Bestand')
return redirect(request.url)
if not os.path.exists("user/Tom/Files/"):
os.makedirs("user/Tom/Files/")
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return render_template("index.html")
if __name__ == ('__main__'):
app.run(debug=True, port=8000)
<!DOCTYPE html>
<html>
<head>
<title>Upload a File!</title>
</head>
<body>
<form method="post" action="user/Tom/Files/" enctype="multipart/form-data">
<input type="file" id="customFile" name="file">
<input type="submit" name="Upload" value="Upload">
</form>
</form>
</body>
</html>
I deleted the action and the value
Now i have this:
<form method="post" enctype="multipart/form-data">
<input type="file" id="customFile" name="file">
<input type="submit" name="Upload">
</form>
But now it stay on de index.html but doesnt upload it to /user/Tom/Files/ ?

Categories