Flask加载CSV至内存并在HTML展示时遇AttributeError问题
Hey there! Let's fix that AttributeError you're hitting. The issue here is that after calling file.save(), the Flask FileStorage object's internal structure changes—its file attribute no longer points to the original temporary file (it becomes a _io.BytesIO instance instead, which doesn't have a file attribute).
Let's walk through solutions based on your needs:
情况1: 你不需要保存文件到本地,只需要加载到内存展示
If your core goal is to load the CSV into memory (as a DataFrame) and display it on the page, you don't even need to save the file to your server. You can read the upload directly:
@app.route('/upload', methods=['GET', 'POST']) def upload(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): # Directly read the FileStorage object with pandas dataframe = pd.read_csv(file) # Convert DataFrame to a format usable in the template data = dataframe.values.tolist() # Grab headers to make the table more readable headers = dataframe.columns.tolist() return render_template("upload.html", data=data, headers=headers) else: return "file not allowed" return render_template("upload.html")
情况2: 你需要保存文件到本地,同时加载到内存
If you must save the file to your server, you have two reliable options:
方案A: Read first, then save
Read the file stream before saving it, then reset the stream position so the save works correctly:
@app.route('/upload', methods=['GET', 'POST']) def upload(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): filename = secure_filename(file.filename) # Read the file into DataFrame first dataframe = pd.read_csv(file) # Reset stream to the start so save() can read it again file.stream.seek(0) # Save the file to your upload folder file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) data = dataframe.values.tolist() headers = dataframe.columns.tolist() return render_template("upload.html", data=data, headers=headers) else: return "file not allowed" return render_template("upload.html")
方案B: Save first, then re-read the saved file
After saving, just open the local file to load into pandas:
import os from flask import Flask, request, render_template from werkzeug.utils import secure_filename import pandas as pd @app.route('/upload', methods=['GET', 'POST']) def upload(): if request.method == 'POST': file = request.files['file'] if file and allowed_file(file.filename): filename = secure_filename(file.filename) file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(file_path) # Read the saved local file into DataFrame dataframe = pd.read_csv(file_path) data = dataframe.values.tolist() headers = dataframe.columns.tolist() return render_template("upload.html", data=data, headers=headers) else: return "file not allowed" return render_template("upload.html")
Fix your HTML template too
Your original form was missing a closing tag, and we'll add header rendering for clarity:
<div class="form-group"> <form method="POST" enctype=multipart/form-data> <input class="btn btn-sm btn-primary" type="file" name="file"> <input type="submit" value='upload'> </form> </div> {% if data %} <table border="1" cellpadding="5" cellspacing="5"> <!-- Render table headers --> <tr> {% for header in headers %} <th>{{ header }}</th> {% endfor %} </tr> <!-- Render data rows --> {% for row in data %} <tr> {% for d in row %} <td>{{ d }}</td> {% endfor %} </tr> {% endfor %} </table> {% endif %}
Quick reminder: Make sure you've defined the allowed_file function, set up UPLOAD_FOLDER in your app config, and created the upload folder on your server to avoid extra errors.
内容的提问来源于stack exchange,提问作者Vikram Karthic

