如何上传文件并用其内容填充网站的某些部分? [英] How to upload a file and populate parts of the website with its content?
问题描述
此处和
There are related questions here and here but they don't solve my problem.
假设我有一个文件testdata.csv
如下:
Let's say I have a file testdata.csv
like this:
A,B
1,3
2,4
,我希望用户允许上传文件,然后-为了简单起见-在同一页面上显示其内容,而不会影响此页面上的任何其他元素.所以我想要的结果看起来像这样:
and I want the user allow to upload the file and then - just for simplicity - display its content on the same page without affecting any other elements on this page. So my desired outcome would look like this:
我该怎么做?我发现了几种使用form
加载文件并将其(修改后的)内容发送回(例如下载)的方法,但是我很难找到一种解决方法来将JSON
响应传回以修改页面(此处:添加表格).
How would I do this? I found a couple of approaches that use a form
to load the file and send its (modified) content back (to e.g. download it) but I struggle to find a solution to pass the JSON
response back to modify the page (here: add the table).
这是我的完整代码:
from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json
# Initialize the Flask application
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/_get_table', methods=["POST", "GET"])
def get_table():
# how to catch the file here and send its content back?
# file = ????
# print(file)
df = pd.DataFrame({"A": [1, 2], "B": [3, 4]})
return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])
# if I use a form, I can use
# file = request.files['myfile']
# however, how do I then send the JSON response?
if __name__ == '__main__':
app.run(debug=True)
和我的index.html
文件:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-center text-muted">Some great stuff</h3>
</div>
<hr class="mb-4">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div><br><br>
<button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>
<hr class="mb-4">
<table id="pretty_table" class="table table-striped"></table>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var table = null;
$('#upload_document').bind('click', function() {
$.getJSON('/_get_table', {
// what to pass here?
}, function(data) {
if (table !== null) {
table.destroy();
table = null;
$("#pretty_table").empty();
}
table = $("#pretty_table").DataTable({
data: data.my_table,
columns: data.columns
});
});
return false;
});
$('.custom-file-input').on('change', function() {
let fileName = $(this).val().split('\\').pop();
$(this).next('.custom-file-label').addClass("selected").html(fileName);
});
});
</script>
</body>
</html>
注释中的
推荐答案
@charlietfl in the comments and this link got me on the right track. One can use FormData
and then an .ajax
call to achieve the desired outcome. So the important parts of above's link are (the complete files can be found below):
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div>
</form>
和
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
和
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/_get_table",
data: data,
processData: false,
processData: false,
对于防止jQuery形式将数据转换为查询字符串很重要,如上面的链接所述.
The processData: false,
is important to prevent jQuery form transforming the data into a query string as explained in the link above.
然后在flask网站上,我们可以通过以下操作轻松地检索文件:
On the flask site, we can then easily retrieve the file by doing:
file = request.files['myfile']
df = pd.read_csv(file)
会将.csv
转换为熊猫数据框.显然,在执行此操作之前,应该先进行检查等.
which turns the .csv
into a pandas dataframe. Clearly, there should be checks etc before doing this.
整个HTML
页面index_formdata.html
看起来像这样:
The entire HTML
page index_formdata.html
would look like this:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
</head>
<body>
<div class="container">
<div class="header">
<h3 class="text-center text-muted">Some great stuff</h3>
</div>
<hr class="mb-4">
<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
<div class="custom-file">
<input id="myfile" name="myfile" type="file" class="custom-file-input">
<label for="myfile" class="custom-file-label">
Choose file...
</label>
</div>
</form><br><br>
<button class="btn btn-primary" type="button" id="upload_document">Upload and process!</button>
<hr class="mb-4">
<table id="pretty_table" class="table table-striped"></table>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var table = null;
$("#upload_document").click(function (event) {
//stop submit the form, we will post it manually.
event.preventDefault();
// Get form
var form = $('#fileUploadForm')[0];
// Create an FormData object
var data = new FormData(form);
// disabled the submit button
$("#upload_document").prop("disabled", true);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
url: "/_get_table",
data: data,
processData: false,
contentType: false,
cache: false,
timeout: 600000,
success: function (data) {
if (table !== null) {
table.destroy();
table = null;
$("#pretty_table").empty();
}
table = $("#pretty_table").DataTable({
data: data.my_table,
columns: data.columns
});
$("#upload_document").prop("disabled", false);
},
error: function (e) {
alert(e.responseText);
console.log("ERROR : ", e);
$("#upload_document").prop("disabled", false);
}
});
});
$('.custom-file-input').on('change', function() {
let fileName = $(this).val().split('\\').pop();
$(this).next('.custom-file-label').addClass("selected").html(fileName);
});
});
</script>
</body>
</html>
flask文件如下:
the flask file as follows:
from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json
# Initialize the Flask application
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index_formdata.html')
@app.route('/_get_table', methods=["POST", "GET"])
def get_table():
# catch file from the form; if you have several files, just make several requests (access by name)
file = request.files['myfile']
df = pd.read_csv(file)
return jsonify(my_table=json.loads(df.to_json(orient="split"))["data"],
columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])
if __name__ == '__main__':
app.run(debug=True)
和testdata.csv
文件
A,B,C
1,3,123
2,4,456
这篇关于如何上传文件并用其内容填充网站的某些部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!