摘要:之前写了一篇前端实现图片下载,大部分场景下,文件下载都可以按照这个思路来实现。其实可以和后台约定返回内容,前端通过监听的内容实现监听。纵观源码,主要实现上传,可借鉴用于下载的方案并没有发现对请求的状态进行监听。
之前写了一篇《前端实现图片下载》,大部分场景下,文件下载都可以按照这个思路来实现。
但是,最近遇到了一个新的需求——POST 下载。服务端只支持 POST 请求,而上一篇文章中涉及的大部分场景都是 GET 请求。
服务端实现以 Node + Koa2 实现为例,服务端返回 excel 文件流
const fs = require("fs") const path = require("path") module.exports = ctx => { ctx.set("Content-Type", "application/vnd.ms-excel") ctx.set("Content-Disposition", "attachment; filename=download.xlsx") ctx.body = fs.createReadStream(path.resolve(__dirname, "./download.xlsx")) }兼容性好的老方案
经典的、兼容性好的方案可以通过构建 Form 表单来实现
let uuidIndex = 0 export default (url, params, method = "post") => { const uuid = `TMP_FRAME_NAME__${uuidIndex++}` const iframe = document.createElement("iframe") iframe.name = uuid iframe.style = "display:none" // 无论响应成功失败,都会调用 onload // iframe.onload = success // iframe.onerror = fail document.body.appendChild(iframe) const form = document.createElement("form") form.action = url form.method = method form.target = uuid form.style = "display:none" form.enctype = "application/x-www-form-urlencoded" document.body.appendChild(form) if (params) { Object.keys(params).forEach(key => { const v = params[key] if (v !== undefined) { const input = document.createElement("input") input.type = "hidden" input.name = key input.value = v form.appendChild(input) } }) } form.submit() document.body.removeChild(form) document.body.removeChild(iframe) }寻找新方案
产品提了一个需求,下载成功要提示,下载失败也要提示。那么问题来了,上面的老方案,不太好监听这次操作是正常还是异常。(其实可以和后台约定返回内容,前端通过监听 iframe 的内容实现监听。)
插曲有个 jQuery 插件 jquery.form.js API 中提供了对成功和失败的回调。纵观源码,主要实现 form 上传,可借鉴用于下载的方案并没有发现对请求的状态进行监听。
正题在经历了以上插曲后,找到一种新的方案。
在新方案中,使用了一些 HTML5 的 API,例如 Blob。所以,兼容性需要 IE 10+ 。
function download(url, name) { const aLink = document.createElement("a") aLink.download = name aLink.href = url aLink.dispatchEvent(new MouseEvent("click", {})) } export default (data, name, type) => { const blob = new Blob([data], { type }) const url = URL.createObjectURL(blob) download(url, name) }demo 一枚
import axios from "axios" // 上面的新方案 import download from "./download" document.getElementById("button").addEventListener("click", () => { axios.post("/download", null, { // 记得设置为成以 buffer 格式读取 responseType: "arraybuffer" }) .then((res) => { // 从响应头里面读取名字,当然,可以自定义 const name = res.headers["content-disposition"].replace(/.*filename=/, "") download(res.data, name, "application/vnd.ms-excel") }) .catch((error) => { console.log(error) }) })吐槽
segmentfault 网站编辑器编辑 markdown 对 js 代码块的解析有 bug,带了箭头函数 // 注释就失效了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/96631.html
摘要:如果像本例中这样的场景会遇到这样一个问题,详见链接当请求参数过长或为了安全,就需要用到下载。写到这里自己都忍不住想锤自己,给自己挖坑不说,这样来回请求下载,流量,真的是败家。 这几天一直在做远程文件下载的事,现在总算有了解决,特来记录一下踩过的坑和想揍自己的心 需求 应用场景是这样的,底层逻辑数据请求接口是由Java写的,也就是说原始文件存在Java服务端,返回时有加密措施 由于工作...
摘要:一前言本文章将以报表下载为例,给大家介绍三种文件下载的方式。通过二进制数据流的方式下载这种方式是我目前采用的方式,用于处理报表下载。缺点对于数据量不大的文件,这种方式是可行的。 一、前言 本文章将以excel报表下载为例,给大家介绍三种文件下载的方式。 原文地址:简谈文件下载的三种方式 | Rychou 二、正文 1. 通过服务器文件地址下载 这是最常见的文件下载方式,大多数网站的音频...
摘要:一前言本文章将以报表下载为例,给大家介绍三种文件下载的方式。通过二进制数据流的方式下载这种方式是我目前采用的方式,用于处理报表下载。缺点对于数据量不大的文件,这种方式是可行的。 一、前言 本文章将以excel报表下载为例,给大家介绍三种文件下载的方式。 原文地址:简谈文件下载的三种方式 | Rychou 二、正文 1. 通过服务器文件地址下载 这是最常见的文件下载方式,大多数网站的音频...
摘要:实现前后端分离的心得对目前的来说,前后端分离已经变得越来越流行了,越来越多的企业网站都开始往这个方向靠拢。前后端工作分配不均。 实现前后端分离的心得 对目前的web来说,前后端分离已经变得越来越流行了,越来越多的企业/网站都开始往这个方向靠拢。那么,为什么要选择前后端分离呢?前后端分离对实际开发有什么好处呢? 为什么选择前后端分离 在以前传统的网站开发中,前端一般扮演的只是切图的工作...
摘要:代码复用总是程序员喜闻乐见的,前端组件化的最终目的就是复用,今天我们就将深入探讨如何实现组件的复用。 懒是第一生产力。 代码复用总是程序员喜闻乐见的,前端组件化的最终目的就是复用,今天我们就将深入探讨如何实现UI组件的复用。 通常我们所说的组件往往是包含业务逻辑的前端组件,而这类组件实际上很难实现广义上的复用,顶多能在同一条业务线上复用一下,但UI组件就不一样了,没有了业务的约束,只在...
阅读 1382·2021-09-02 09:53
阅读 2656·2021-07-29 13:50
阅读 1694·2019-08-30 11:07
阅读 1554·2019-08-30 11:00
阅读 1437·2019-08-29 14:00
阅读 1786·2019-08-29 12:52
阅读 2542·2019-08-29 11:11
阅读 3399·2019-08-26 12:23