ajax post下载flask文件流以及中文文件名

  • ajax post下载文件

    后端返回文件流,flask中可使用return send_file(文件路径)返回二进制文件流,在headers中传送文件相关信息(如文件名)。

    前端使用URL.createObjectURL()创建创建一个 DOMStringURL对象,创建一个a节点,将URL对象赋给a节点的href属性,最后调用click()方法点击该a节点即可弹出浏览器下载框。

  • 展示图片

    方法同上,将a改成imghref改成src即可,将URL对象写入到目标img标签的src即可。
    另一种方法是后端返回图片转base64的字符串,src的值形如"data:image/svg+xml;base64,${base字符串}"。(这里的svg+xml表示图片格式是svg,如果是png则改成png)

  • 中文文件名乱码

    http headers中直接传输中文文件名,比较简单的方法是后端进行url转码(这里使用python的urllib.parse.quote),前端使用decodeURI()解码。
    此外还可以设置headers的Content-Disposition: attachment; filename*=UTF-8''xxxxx,不过兼容性嘛……麻烦还不如直接urlcode算了,而且也懒得设置Content-Disposition了,前端从Content-Disposition中取filename也是够麻烦的,会取到一长串字符串然后自己再想办法取出来filename=后面的信息。

代码如下:

flask

from urllib.parse import quote
@file.route('/download', methods=["POST"])
def download_file():
    filename='xx' #文件名
    filepath='xx/xx'  #文件路径
    res = make_response(send_file(filepath))
    #自定义的一个header,方便前端取到名字
    res.headers['filename'] = quote(filename.encode('utf-8'))
    return res

javascript——以async异步fetch为例:

async function download() {
    const res = await fetch(`http://xxx/file/download`, {
    method: "POST",
    body: JSON.stringify({}),  //body里面是要发送的数据
    headers: { "Content-Type": "application/json" },
    responseType: 'blob'
  })

  if (res.ok) {
    const blData = await res.blob()  //拿到blob数据
    const urlObjData = window.URL.createObjectURL(new Blob([blData]))  //创建url对象
    
    //获取文件 进行下转码
    const fileName = decodeURI(fileNameres.headers.get('filename'))
    
    //创建a标签 点击a标签 达到下载目的
    const link = document.createElement('a')
    link.href = urlObjData
    link.download = fileName //下载文件的名字
    document.body.appendChild(link)
    link.click()
    
    document.body.removeChild(link)
    window.URL.revokeObjectURL(urlObjData);
    
    //展示图片
    //xxx.src=urlObjData
  }
}

你可能感兴趣的:(flask,ajax,javascript,前端)