摘要:之前寫(xiě)了一篇前端實(shí)現(xiàn)圖片下載,大部分場(chǎng)景下,文件下載都可以按照這個(gè)思路來(lái)實(shí)現(xiàn)。其實(shí)可以和后臺(tái)約定返回內(nèi)容,前端通過(guò)監(jiān)聽(tīng)的內(nèi)容實(shí)現(xiàn)監(jiān)聽(tīng)??v觀源碼,主要實(shí)現(xiàn)上傳,可借鑒用于下載的方案并沒(méi)有發(fā)現(xiàn)對(duì)請(qǐng)求的狀態(tài)進(jìn)行監(jiān)聽(tīng)。
之前寫(xiě)了一篇《前端實(shí)現(xiàn)圖片下載》,大部分場(chǎng)景下,文件下載都可以按照這個(gè)思路來(lái)實(shí)現(xiàn)。
但是,最近遇到了一個(gè)新的需求——POST 下載。服務(wù)端只支持 POST 請(qǐng)求,而上一篇文章中涉及的大部分場(chǎng)景都是 GET 請(qǐng)求。
服務(wù)端實(shí)現(xiàn)以 Node + Koa2 實(shí)現(xiàn)為例,服務(wù)端返回 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")) }兼容性好的老方案
經(jīng)典的、兼容性好的方案可以通過(guò)構(gòu)建 Form 表單來(lái)實(shí)現(xiàn)
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" // 無(wú)論響應(yīng)成功失敗,都會(huì)調(diào)用 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) }尋找新方案
產(chǎn)品提了一個(gè)需求,下載成功要提示,下載失敗也要提示。那么問(wèn)題來(lái)了,上面的老方案,不太好監(jiān)聽(tīng)這次操作是正常還是異常。(其實(shí)可以和后臺(tái)約定返回內(nèi)容,前端通過(guò)監(jiān)聽(tīng) iframe 的內(nèi)容實(shí)現(xiàn)監(jiān)聽(tīng)。)
插曲有個(gè) jQuery 插件 jquery.form.js API 中提供了對(duì)成功和失敗的回調(diào)??v觀源碼,主要實(shí)現(xiàn) form 上傳,可借鑒用于下載的方案并沒(méi)有發(fā)現(xiàn)對(duì)請(qǐng)求的狀態(tài)進(jìn)行監(jiān)聽(tīng)。
正題在經(jīng)歷了以上插曲后,找到一種新的方案。
在新方案中,使用了一些 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, { // 記得設(shè)置為成以 buffer 格式讀取 responseType: "arraybuffer" }) .then((res) => { // 從響應(yīng)頭里面讀取名字,當(dāng)然,可以自定義 const name = res.headers["content-disposition"].replace(/.*filename=/, "") download(res.data, name, "application/vnd.ms-excel") }) .catch((error) => { console.log(error) }) })吐槽
segmentfault 網(wǎng)站編輯器編輯 markdown 對(duì) js 代碼塊的解析有 bug,帶了箭頭函數(shù) // 注釋就失效了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/96631.html
摘要:如果像本例中這樣的場(chǎng)景會(huì)遇到這樣一個(gè)問(wèn)題,詳見(jiàn)鏈接當(dāng)請(qǐng)求參數(shù)過(guò)長(zhǎng)或?yàn)榱税踩托枰玫较螺d。寫(xiě)到這里自己都忍不住想錘自己,給自己挖坑不說(shuō),這樣來(lái)回請(qǐng)求下載,流量,真的是敗家。 這幾天一直在做遠(yuǎn)程文件下載的事,現(xiàn)在總算有了解決,特來(lái)記錄一下踩過(guò)的坑和想揍自己的心 需求 應(yīng)用場(chǎng)景是這樣的,底層邏輯數(shù)據(jù)請(qǐng)求接口是由Java寫(xiě)的,也就是說(shuō)原始文件存在Java服務(wù)端,返回時(shí)有加密措施 由于工作...
摘要:一前言本文章將以報(bào)表下載為例,給大家介紹三種文件下載的方式。通過(guò)二進(jìn)制數(shù)據(jù)流的方式下載這種方式是我目前采用的方式,用于處理報(bào)表下載。缺點(diǎn)對(duì)于數(shù)據(jù)量不大的文件,這種方式是可行的。 一、前言 本文章將以excel報(bào)表下載為例,給大家介紹三種文件下載的方式。 原文地址:簡(jiǎn)談文件下載的三種方式 | Rychou 二、正文 1. 通過(guò)服務(wù)器文件地址下載 這是最常見(jiàn)的文件下載方式,大多數(shù)網(wǎng)站的音頻...
摘要:一前言本文章將以報(bào)表下載為例,給大家介紹三種文件下載的方式。通過(guò)二進(jìn)制數(shù)據(jù)流的方式下載這種方式是我目前采用的方式,用于處理報(bào)表下載。缺點(diǎn)對(duì)于數(shù)據(jù)量不大的文件,這種方式是可行的。 一、前言 本文章將以excel報(bào)表下載為例,給大家介紹三種文件下載的方式。 原文地址:簡(jiǎn)談文件下載的三種方式 | Rychou 二、正文 1. 通過(guò)服務(wù)器文件地址下載 這是最常見(jiàn)的文件下載方式,大多數(shù)網(wǎng)站的音頻...
摘要:實(shí)現(xiàn)前后端分離的心得對(duì)目前的來(lái)說(shuō),前后端分離已經(jīng)變得越來(lái)越流行了,越來(lái)越多的企業(yè)網(wǎng)站都開(kāi)始往這個(gè)方向靠攏。前后端工作分配不均。 實(shí)現(xiàn)前后端分離的心得 對(duì)目前的web來(lái)說(shuō),前后端分離已經(jīng)變得越來(lái)越流行了,越來(lái)越多的企業(yè)/網(wǎng)站都開(kāi)始往這個(gè)方向靠攏。那么,為什么要選擇前后端分離呢?前后端分離對(duì)實(shí)際開(kāi)發(fā)有什么好處呢? 為什么選擇前后端分離 在以前傳統(tǒng)的網(wǎng)站開(kāi)發(fā)中,前端一般扮演的只是切圖的工作...
摘要:代碼復(fù)用總是程序員喜聞樂(lè)見(jiàn)的,前端組件化的最終目的就是復(fù)用,今天我們就將深入探討如何實(shí)現(xiàn)組件的復(fù)用。 懶是第一生產(chǎn)力。 代碼復(fù)用總是程序員喜聞樂(lè)見(jiàn)的,前端組件化的最終目的就是復(fù)用,今天我們就將深入探討如何實(shí)現(xiàn)UI組件的復(fù)用。 通常我們所說(shuō)的組件往往是包含業(yè)務(wù)邏輯的前端組件,而這類(lèi)組件實(shí)際上很難實(shí)現(xiàn)廣義上的復(fù)用,頂多能在同一條業(yè)務(wù)線(xiàn)上復(fù)用一下,但UI組件就不一樣了,沒(méi)有了業(yè)務(wù)的約束,只在...
閱讀 1414·2021-09-02 09:53
閱讀 2677·2021-07-29 13:50
閱讀 1726·2019-08-30 11:07
閱讀 1583·2019-08-30 11:00
閱讀 1461·2019-08-29 14:00
閱讀 1853·2019-08-29 12:52
閱讀 2572·2019-08-29 11:11
閱讀 3429·2019-08-26 12:23