使用 Flask 和 JS 从服务器下载文件

问题描述 投票:0回答:3

当用户单击特定按钮时,我尝试下载文件。该文件是按下所述按钮时创建的图像。我想要的是,它应该自动将图像下载到客户端设备上。

我在服务器代码上使用 Flask,理想情况下,Flask 的

send_file
功能应该触发此自动下载,因为它添加了
Content-Disposition
标头。

在客户端,我有一个JS代码,它使用fetch API向服务器发送带有一些数据的POST请求,这些数据用于生成要下载的图像。

这是JS代码:

function make_image(text){
    const json={
        text: text
    };
    const options={
        method: "POST",
        body: JSON.stringify(json),
        headers:{
            'Content-Type':'application/json',
        }
    };

    fetch('/image',options)
        .then(res=>{
            res.json(); //Gives an error: Uncaught (in promise) SyntaxError: Unexpected token � in JSON at position 0
        }).catch(err=>console.log(err));
}

这是服务器上的Python代码:

@app.route('/image',methods=['POST'])
def generate_image():
    cont = request.get_json()
    t=cont['text']
    print(cont['text'])
    name = pic.create_image(t)
    time.sleep(2)
    return send_file(f"{name}.png",as_attachment=True,mimetype="image/png")

但是什么也没发生。图像未下载。但是,图像是在服务器上创建的并且没有损坏

我该如何解决这个问题?还有其他方法可以完成我想做的事情吗?

javascript python-3.x flask httprequest fetch-api
3个回答
0
投票

您可以执行以下操作

return send_from_directory(dir, file_name, as_attachment=True)

这会将文件下载到用户的计算机上。

编辑:

顺便说一句,如果您创建如下所示的 html 表单,则不需要 javascript。

<form action='action here' method='post'>
    <input type='submit'>
</form>

0
投票

正如@clockwatcher提到的另一个问题,我使用了

download.js
模块来处理图像的下载。

所以我的 JS 代码现在看起来像这样:

function make_image(text){
    const json={
        text: text
    };
    const options={
        method: "POST",
        body: JSON.stringify(json),
        headers:{
            'Content-Type':'application/json',
        }
    };

    fetch('/image',options)
        .then(res=>{
            return res.blob();
        }).then(blob=>{
            download(blob)
        }).catch(err=>console.log(err));
}

以及在 html 中添加 script 标签:

<script src="https://cdnjs.cloudflare.com/ajax/libs/downloadjs/1.4.8/download.min.js"></script>

Python 服务器代码没有变化。

现在可以使用了


0
投票

您的代码中的错误是在 Javascript 中 从 Python 服务器发送的响应是一个文件

return send_file(f"{name}.png",as_attachment=True,mimetype="image/png")

但是,您要使用 json() 方法将响应(按预期文件)转换为 JSON

    ...

    fetch('/image',options)
        .then(res=>{
            res.json(); // **
        }).catch(err=>console.log(err));

您想要做的是使用 blob() 方法以 blob 形式接收文件

编辑 为了自动下载,您需要创建一个锚元素,定义其下载属性并自动单击它

在你的JS中

    ...

    fetch('/image',options)
        .then((res)=>{
            return res.blob()
        }).then((blob)=>{
           let el = document.createElement("a"); 
           // creates anchor element but doesn't add it to the DOM
           el.setAttribute("download", [filename]) 
           // make the link downloadable on click
           let url = URL.createObjectUrl(blob); 
           // creates a url to the retrieved file
           el.href = url; // set the href attribute attribute
           el.click(); 
        })
    // catch errors
    .catch(err=>console.log(err));

© www.soinside.com 2019 - 2024. All rights reserved.