简体   繁体   中英

Uploading file in Flask with only .csv allowed extension

I'm creating a form that allows you to upload a.csv file and then on submit, posts the values inside the csv file to the database.

My problem is that I want to be able to use request.files[] to implement a logic check that only accepts.csv extension files for upload, however, I am not able to use request.files[] when trying to open my csv file with with open(f, 'r') below.

I get this error: "Unexpected type(s): (FileStorage, str) Possible type(s): (Union[str, bytes, PathLike[str], PathLike[bytes], int], str)..."

If I used request.form[], I don't have the error with opening the file, however, then I can't use the "filename" attribute for the logic check as that requires request. files [].

Here is my routes file:

allowed_extensions = ['csv']

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in allowed_extensions

@main.route("/reading_csv", methods=['POST'])
def reading_csv():
    if request.method == 'POST':
        f = request.files['csvfile']
        # logic check
        if not allowed_file(f.filename):
            flash("Only CSV Files Allowed", 'danger')
            return redirect(url_for('main.alloc_summ'))
        # opening file, reading it in, and inserting values to database
        with open(f, 'r') as csv_file:
            csv_reader = csv.DictReader(csv_file, delimiter=',')
            all_values = [tuple(line.values()) for line in csv_reader]

        con = sql.connect('<hidden path url>')
        cur = con.cursor()

        cur.executemany('INSERT INTO allocation_summary \
                        (state, eligible_applicant, recipient, amount, funding_source_id) \
                            VALUES (?,?,?,?,?)', all_values)
        con.commit()

        cur.close()
        con.close()

        flash("Allocations Added Successfully")
        return redirect(url_for('main.alloc_summ'))

Here is the HTML:

                    <td>
                        <form class="" action="{{url_for('main.reading_csv')}}" method="post" enctype="multipart/form-data">
                            <input style="margin-bottom: 5px;" type="file" accept=".csv" name="csvfile" value =""> <br>
                            <input style="margin-bottom: 10px;" type="submit" name="" value="Submit">
                        </form>
                    <br>
                    </td>

I can't open my file using the "f" variable that holds the requested file.

Is there any work around to this? TIA!!

Use .save() method to save your file, don't try to open it

f.save(path: str, filename: str)

Upd:

Read Flask: How to upload file to understand the basic of multipart handling in Flask

FileStorage is a file-like object that understands standard reading functions. It corresponds to a temporary file opened in binary mode. So you don't have to open this file again.
In order to be able to read a CSV file, it should be opened in text mode. This results in a contradiction.
The following example should show you one way to meet your requirements.

import csv, io

allowed_extensions = ['csv']

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in allowed_extensions

@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST' and 'csvfile' in request.files:
        f = request.files['csvfile']
        if f.filename != '' and allowed_file(f.filename):
            with io.TextIOWrapper(f) as fp:
                reader = csv.DictReader(fp, delimiter=',')
                values = [tuple(line.values()) for line in reader]
                print(values)
                # ...
    return render_template('upload.html')
<form class="" action="{{url_for('upload')}}" method="post" enctype="multipart/form-data">
    <input type="file" accept="text/csv" name="csvfile" />
    <input type="submit" />
</form>

Please keep in mind that a file can become very large and contains data that should be validated before it is included in your database. Perhaps saving the file as @sudden_appearance describes is a more appropriate solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM