2

I am making a data visualization tool that takes input from the user (choosing a file on the computer); processes it in Python with Pandas, Numpy, etc; and displays the data in the browser on a local server.

I am having trouble accessing the data once the file is selected using an HTML input form.

HTML form:

<form action="getfile" method="POST" enctype="multipart/form-data">
    Project file path: <input type="file" name="myfile"><br>
    <input type="submit" value="Submit">
</form>

Flask routing:

@app.route("/")
def index():
    return render_template('index.html')

@app.route('/getfile', methods=['GET','POST'])
def getfile():
    if request.method == 'POST':
        result = request.form['myfile']
    else:
        result = request.args.get['myfile']
    return result

This returns a "Bad Request The browser (or proxy) sent a request that this server could not understand." error. I have tried a number of different ways of getting the data out of the file and simply printing it to the screen to start, and have received a range of errors including "TypeError: 'FileStorage' object is not callable" and "ImmutableMultiDict' object is not callable". Any pointers on how to approach this task correctly are appreciated.

K Hutch
  • 113
  • 2
  • 3
  • 13
  • Try returning something else and see if that works. I believe `result = request.form['myfile']` part should work. Also, do not even try to support uploading a file using GET. That is not going to work well. – zvone Oct 01 '16 at 00:27

2 Answers2

4

Try this. I've been working on saving and unzipping files for the last few days. If you have any trouble with this code, let me know :)

I'd suggest saving the file on disk and then reading it. If you don't want to do that, you needn't.

from flask import Flask, render_template, request
from werkzeug import secure_filename

@app.route('/getfile', methods=['GET','POST'])
def getfile():
    if request.method == 'POST':

        # for secure filenames. Read the documentation.
        file = request.files['myfile']
        filename = secure_filename(file.filename) 

        # os.path.join is used so that paths work in every operating system
        file.save(os.path.join("wherever","you","want",filename))

        # You should use os.path.join here too.
        with open("wherever/you/want/filename") as f:
            file_content = f.read()

        return file_content     


    else:
        result = request.args.get['myfile']
    return result

And as zvone suggested in the comments, I too would advise against using GET to upload files.

Uploading files
os.path by Effbot

Edit:-

You don't want to save the file.

Uploaded files are stored in memory or at a temporary location on the filesystem. You can access those files by looking at the files attribute on the request object. Each uploaded file is stored in that dictionary. It behaves just like a standard Python file object, but it also has a save() method that allows you to store that file on the filesystem of the server.

I got this from the Flask documentation. Since it's a Python file you can directly use file.read() on it without file.save().

Also if you need to save it for sometime and then delete it later, you can use os.path.remove to delete the file after saving it. Deleting a file in Python

Community
  • 1
  • 1
Abhirath Mahipal
  • 938
  • 1
  • 10
  • 21
  • Thank you, this worked wonderfully! I will be using POST; I threw GET in during troubleshooting. Since the file will be saved locally on the computer already, I think I will prefer not to be saving it again with this program unless there is a benefit to it - I just need to access the text inside. I really appreciate your clear response! – K Hutch Oct 01 '16 at 20:50
1

A input type=file data isn't passed in as the form dictionary of a request object. It is passed in as request.files (files dictionary in the request object).

So simply change:

result = request.form['myfile']

to

result = request.files['myfile']
oxalorg
  • 2,768
  • 1
  • 16
  • 27
  • thank you for clarifying this point! However, I tried this and received the following error: "TypeError: 'FileStorage' object is not callable" – K Hutch Oct 01 '16 at 14:35
  • @KHutch because you can't `return` a file object as a view response. You need to read it and return a valid response from the view function `getfile`. Try something like `return result.filename` to test if the uploading works. – oxalorg Oct 01 '16 at 14:39
  • @oxalorg. I get "AttributeError: module 'request' has no attribute 'form'". I get the similar error for files. Is there any other solution? – Eswar Jan 29 '19 at 10:16