Last active
November 9, 2020 07:42
-
-
Save mrxf/14091139d710a7e4d9d79b71e1472243 to your computer and use it in GitHub Desktop.
xhr download file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Button, Card, message, Progress, Space } from "antd"; | |
import Axios, { CancelTokenSource } from "axios"; | |
import contentDisposition from "content-disposition"; | |
import React, { useCallback, useRef, useState } from "react"; | |
interface DownloadProps {} | |
const Download: React.FC<DownloadProps> = () => { | |
const cancelSource = useRef<CancelTokenSource | null>(null); | |
const [percentage, setPercentage] = useState<number>(0); | |
const triggerDownload = useCallback((data: any, fileName: string) => { | |
let url = window.URL.createObjectURL(new Blob([data])); | |
let link = document.createElement("a"); | |
link.style.display = "none"; | |
link.href = url; | |
link.setAttribute("download", fileName); | |
document.body.appendChild(link); | |
link.click(); | |
}, []); | |
const onDownload = useCallback( | |
(url: string) => { | |
return new Promise(async (resolve, reject) => { | |
const CancelToken = Axios.CancelToken; | |
cancelSource.current = CancelToken.source(); | |
try { | |
const response = await Axios.get(url, { | |
// 文件类型设置 | |
responseType: "blob", | |
headers: { | |
Authorization: `Bearer Token`, // 授权信息 | |
}, | |
cancelToken: cancelSource.current.token, | |
onDownloadProgress(evt) { | |
setPercentage(Math.ceil((evt.loaded / evt.total) * 100)); | |
}, | |
}); | |
if (response.status === 200) { | |
let fileName = ""; | |
if ("content-disposition" in response.headers) { | |
// 从Header中获取文件名 | |
const dispositionParams = contentDisposition.parse( | |
response.headers["content-disposition"] | |
).parameters; | |
fileName = dispositionParams["filename"]; | |
} | |
triggerDownload(response.data, fileName); | |
resolve("success"); | |
} else { | |
reject("response status" + response.status); | |
} | |
} catch (error) { | |
// Axios的错误类型,读取返回数据中的JSON内容 | |
if (error.isAxiosError) { | |
// 因为数据默认设置为Blob文件类型,因此需要使用fileReader将数据从Blob中读取出来 | |
const fr = new FileReader(); | |
fr.onload = function () { | |
const result = JSON.parse((this.result as string) ?? "{}"); | |
// 与后端协定的数据格式,根据实际情况改动 | |
reject(result.message); | |
}; | |
fr.readAsText(error.response.data); | |
} else { | |
// 其他错误类型,直接返回消息体 | |
reject(error.message); | |
} | |
} | |
}); | |
}, | |
[triggerDownload] | |
); | |
const onClickDownload = useCallback(() => { | |
setPercentage(0); | |
onDownload("/api/download/attachment-image").then( | |
() => { | |
message.success("下载成功"); | |
}, | |
(err) => message.error(err) | |
); | |
}, [onDownload]); | |
const onCancel = useCallback(() => { | |
setPercentage(0); | |
cancelSource.current?.cancel("用户取消下载"); | |
}, []); | |
const onClickUnAuthDownload = useCallback(() => { | |
onDownload("/api/download/download-unauth").then( | |
() => { | |
message.success("下载成功"); | |
}, | |
(err) => message.error(err) | |
); | |
}, [onDownload]); | |
return ( | |
<div className='inner-card'> | |
<Card> | |
<div style={{ display: "flex", justifyContent: "center" }}> | |
<Space> | |
<Button type='primary' disabled={ !!percentage && percentage !== 100 } onClick={onClickDownload}> | |
开始下载 | |
</Button> | |
<Button type='dashed' onClick={onCancel}> | |
取消下载 | |
</Button> | |
<Progress type='circle' percent={percentage} /> | |
</Space> | |
</div> | |
</Card> | |
<Card> | |
<Button onClick={onClickUnAuthDownload} danger> | |
测试下载错误 | |
</Button> | |
</Card> | |
</div> | |
); | |
}; | |
export default Download; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment