简体   繁体   English

在 Flask 中上传文件,仅允许扩展名.csv

[英]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.我正在创建一个表单,允许您上传.csv 文件,然后在提交时将 csv 文件中的值发布到数据库。

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.我的问题是我希望能够使用 request.files[] 来实现只接受.csv 扩展文件进行上传的逻辑检查,但是,在尝试打开我的 csv 时我无法使用 request.files[]下面with open(f, 'r')文件。

I get this error: "Unexpected type(s): (FileStorage, str) Possible type(s): (Union[str, bytes, PathLike[str], PathLike[bytes], int], str)..."我收到此错误: “意外类型:(FileStorage,str)可能的类型:(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.如果我使用 request.form[],打开文件时不会出现错误,但是,我不能使用“文件名”属性进行逻辑检查,因为这需要请求。 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:这是 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.我无法使用包含所请求文件的“f”变量打开我的文件。

Is there any work around to this?有什么解决方法吗? TIA!!蒂亚!!

Use .save() method to save your file, don't try to open it使用.save()方法保存文件,不要尝试打开它

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

Upd:更新:

Read Flask: How to upload file to understand the basic of multipart handling in Flask阅读Flask:如何上传文件以了解 Flask 中多部分处理的基础知识

FileStorage is a file-like object that understands standard reading functions. FileStorage 是一个类文件 object 理解标准读取功能。 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.为了能够读取 CSV 文件,它应该以文本模式打开。 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.也许将文件保存为@sudden_appearance 描述的更合适的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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