Python 从API下载文件
我将一个文件从网页发送到Flask服务器,对其执行一些转换,然后我想返回转换后的文档,以便用户可以下载它。我有一个按钮,这将发送POST请求:Python 从API下载文件,python,rest,flask,download,Python,Rest,Flask,Download,我将一个文件从网页发送到Flask服务器,对其执行一些转换,然后我想返回转换后的文档,以便用户可以下载它。我有一个按钮,这将发送POST请求: fileUpload: function(file) { var formData = new FormData(); formData.append('file',file); var xhr = new XMLHttpRequest(); xhr.addEventListener("load", () =>
fileUpload: function(file) {
var formData = new FormData();
formData.append('file',file);
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", () => {
console.log("asdf");
});
xhr.open("POST", "http://localhost:7733/receivedoc");
xhr.send(formData);
}
然后在服务器上,我执行转换并希望返回一个文件:
...
#Transformations, save file to the file system
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
但是,我的浏览器中没有任何文件下载。没有错误,请求似乎通过了OK。请求头是
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9,en-US;q=0.8,hu;q=0.7,cs;q=0.6,sk;q=0.5,de;q=0.4
Connection: keep-alive
Content-Length: 114906
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarycEQwQtGAXe1ysM9b
DNT: 1
Host: localhost:7733
Origin: http://localhost:5000
Referer: http://localhost:5000/
以及请求有效负载:
------WebKitFormBoundarycEQwQtGAXe1ysM9b
Content-Disposition: form-data; name="file"; filename="response.xls"
Content-Type: application/octet-stream
------WebKitFormBoundarycEQwQtGAXe1ysM9b--
response.xls
正是我想要下载的文件。我怎样才能下载它
更新-尝试实施Joost的解决方案。我愿意:
@app.route('/receivedoc', methods=['POST', 'GET', 'OPTIONS'])
@crossdomain(origin='*')
def upload_file():
if request.method == 'POST':
#TRANSFORMING FILE, then saving below:
writer = pd.ExcelWriter(filename)
df_output.to_excel(writer,'Pacing', index=False)
writer.save()
return send_from_directory(directory=app.config['UPLOAD_FOLDER'], filename=filename)
if request.method == 'GET':
prefixed = [filename for filename in os.listdir(app.config['UPLOAD_FOLDER']) if filename.startswith("PG PEIT")]
filename = max(prefixed)
print("what what")
return render_template_string('''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Your file is ready</title>
</head>
<body>
<form enctype="multipart/form-data" method="post" name="fileinfo">
<input type="text" name="fname" required />
<input type="submit" value="request the file!" />
</form>
<script>
function saveBlob(blob, fileName) {
var a = document.createElement("a");
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
document.body.appendChild(a); // won't work in firefox otherwise
a.click();
}
var form = document.forms.namedItem("fileinfo");
form.addEventListener('submit', function(ev) {
var oData = new FormData(form);
var oReq = new XMLHttpRequest();
oReq.responseType = 'blob';
oReq.open("POST", "{{url_for('upload_file')}}", true);
oReq.onload = function(oEvent) {
if (oReq.status == 200) {
var blob = oReq.response;
var fileName = 'response.xml'
saveBlob(blob, fileName);
} else {
alert("Error " + oReq.status + " occurred")
}
};
oReq.send(oData);
ev.preventDefault();
}, false);
</script>
</body>
</html>
''')
@app.route('/receivedoc',方法=['POST','GET','OPTIONS'])
@跨域(原点=“*”)
def upload_文件():
如果request.method==“POST”:
#转换文件,然后保存以下内容:
writer=pd.ExcelWriter(文件名)
df_输出到excel(写入程序,'packing',索引=False)
writer.save()
从_目录返回发送_(directory=app.config['UPLOAD_FOLDER'],filename=filename)
如果request.method==“GET”:
前缀=[如果filename.startswith(“PG PEIT”)]则为os.listdir(app.config['UPLOAD_FOLDER'])中文件名的文件名]
filename=max(前缀)
打印(“什么”)
返回渲染模板字符串(“”)
你的文件准备好了
函数saveBlob(blob,文件名){
var a=document.createElement(“a”);
a、 href=window.URL.createObjectURL(blob);
a、 下载=文件名;
document.body.appendChild(a);//否则将无法在firefox中工作
a、 单击();
}
var form=document.forms.namedItem(“fileinfo”);
表单.addEventListener('submit',函数(ev){
var oData=新表单数据(表单);
var oReq=新的XMLHttpRequest();
oReq.responseType='blob';
open(“POST”,“{{url\u for('upload\u file')}}”,true);
oReq.onload=功能(oEvent){
如果(oReq.status==200){
var blob=oReq.响应;
var fileName='response.xml'
saveBlob(blob,文件名);
}否则{
警报(“错误”+oReq.status+“发生”)
}
};
oReq.send(oData);
ev.preventDefault();
},假);
''')
这将给我一个很好的.html响应,但该文件仍然无法下载:
我误解了什么?这主要是一个javascript问题,python与此无关。几周前我也遇到了同样的问题,所以我决定做一个小例子来演示一个实用的应用程序。主要的技巧是将数据保存在js中,使用数据创建一个可下载的链接,并让js单击它 全功能示例:
from flask import Flask, render_template_string, request, url_for, send_from_directory
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
fname = request.form['fname']
return send_from_directory('', fname, as_attachment=True)
return render_template_string('''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
</head>
<body>
<form enctype="multipart/form-data" method="post" name="fileinfo">
<input type="text" name="fname" required />
<input type="submit" value="request the file!" />
</form>
<script>
function saveBlob(blob, fileName) {
var a = document.createElement("a");
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
document.body.appendChild(a); // won't work in firefox otherwise
a.click();
}
var form = document.forms.namedItem("fileinfo");
form.addEventListener('submit', function(ev) {
var oData = new FormData(form);
var oReq = new XMLHttpRequest();
oReq.responseType = 'blob';
oReq.open("POST", "{{url_for('index')}}", true);
oReq.onload = function(oEvent) {
if (oReq.status == 200) {
var blob = oReq.response;
var fileName = 'response.xml'
saveBlob(blob, fileName);
} else {
alert("Error " + oReq.status + " occurred")
}
};
oReq.send(oData);
ev.preventDefault();
}, false);
</script>
</body>
</html>
''')
app.run()
从flask导入flask,呈现模板字符串,请求,url,从目录发送
app=烧瓶(名称)
@app.route('/',方法=['GET','POST'])
def index():
如果request.method==“POST”:
fname=request.form['fname']
从_目录返回发送_(“”,fname,as_attachment=True)
返回渲染模板字符串(“”)
标题
函数saveBlob(blob,文件名){
var a=document.createElement(“a”);
a、 href=window.URL.createObjectURL(blob);
a、 下载=文件名;
document.body.appendChild(a);//否则将无法在firefox中工作
a、 单击();
}
var form=document.forms.namedItem(“fileinfo”);
表单.addEventListener('submit',函数(ev){
var oData=新表单数据(表单);
var oReq=新的XMLHttpRequest();
oReq.responseType='blob';
open(“POST”,“{{url_for('index')}}”,true);
oReq.onload=功能(oEvent){
如果(oReq.status==200){
var blob=oReq.响应;
var fileName='response.xml'
saveBlob(blob,文件名);
}否则{
警报(“错误”+oReq.status+“发生”)
}
};
oReq.send(oData);
ev.preventDefault();
},假);
''')
app.run()
这看起来确实是一个解决方案,但似乎对我不起作用。当我检查控制台时,我确实在网页上的呼叫响应中得到了整个html部分,但是,下载仍然不会发生。不,但是如果它在Chrome中无法工作,那么我需要另一个解决方案。我只是再次尝试。它可以在firefox和chrome中使用。只需复制示例,看看是否可以运行它。然后从那里工作回来。