1. 태그 다운로드 다운로드
백엔드는 다운로드 가능한 url 파일 또는 프런트 엔드에 로컬로 저장된 파일을 반환하고 경로를 통해 다운로드합니다.
(1) 로컬 저장을 위해 프런트 엔드에 리소스를 넣고 패키징 후 서버에서 업로드
// 本地资源下载,引入路径即可,这里的路径指的是打包后文件与代码文件的相对路径
<a href="./import-template.xlsx" download target="_blank">
下载上传模板
</a>
(2) 서버를 요청하고 반환 된 url을 태그의 href 속성에 넣습니다.
다음은 의사 코드입니다. 구현 단계에서는 먼저 url을 가져 와서 변수로 사용하여 a의 href 속성에 넣습니다. 태그입니다. 다른 프레임 워크 방법은 다릅니다.
let requestUrl = 'xxxxxx';
let responseUrl = '';
fetch(requestUrl ).then(res => {
responseUrl = res.data.url
})
// dom节点渲染如果responseUrl出现跨域,download将失效,无法下载
<a href=`${
responseUrl }` download target="_blank">
下载上传模板
</a>
(3) 프레임 워크에 의존하지 않고 네이티브 js는 클릭 및 다운로드 방법을 인식합니다.
//点击某个按钮触发事件
const onClickDownFile = (id) => {
let requestUrl = `xxxxxx${
id}xxxx`;
fetch(requestUrl).then(res => {
//为了解决a标签跨域无法下载的问题
const x = new XMLHttpRequest();
x.open('GET', res.data.url, true);
x.responseType = 'blob';
x.onload = () => {
const dataurl = window.URL.createObjectURL(x.response);
const a = document.createElement('a');
a.href = res.data.url;
a.download = res.data.url;
a.click();
a.remove();
};
x.send();
})
};
2. 백엔드 인터페이스는 바이너리 스트림을 반환하고 프런트 엔드는 수신 및 처리해야합니다.
import {
stringify } from 'qs';
type Method = 'GET' | 'POST';
/**
* 下载文件
* @param url 接口路径
* @param data 请求的参数
* @param method 请求方式
* @param type 下载文件的类型
* @param fileName 自定义文件名称
*/
export const download = (
url: string,
data: any,
method: Method,
type: string,
fileName?: string,
) => {
/** fetch 配置项 */
const params: RequestInit = {
method,
headers: {
Authorization: '',
'response-type': 'arraybuffer',
},
};
if (method === 'GET') {
// 每次请求添加时间戳,避免 GET 请求遭遇 HTTP 缓存
data._ = new Date().getTime();
// 请求参数合并到 URL 上
url += `?${
stringify(data)}`;
} else {
params.body = JSON.stringify(data);
}
return fetch(url, params)
.then((response) => {
if (response.status === 200 && response.body) {
if (!fileName) {
const cd = response.headers.get('content-disposition');
const cds = cd?.split('filename=') || [];
if (cds[1]) {
fileName = decodeURIComponent(cds[1]);
}
}
return response.blob();
}
return Promise.reject();
})
.then((_blob) => {
const blob = new Blob([_blob], {
type,
});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName || 'file';
link.click();
return 'done';
});
};
사용하는 방법
download(
’xxxx‘,
{
},
"GET", //或者"POST"
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
fileName, //文件名称
)
type은 파일 유형이고 다른 파일 유형에는 다른 유형이 있습니다.
접미사 | MIME 유형 |
---|---|
.문서 | 응용 프로그램 / msword |
.docx | application / vnd.openxmlformats-officedocument.wordprocessingml.document |
.xls | 애플리케이션 /vnd.ms-excel |
.xlsx | application / vnd.openxmlformats-officedocument.spreadsheetml.sheet |
.ppt | application / vnd.ms-powerpoint |
.pptx | application / vnd.openxmlformats-officedocument.presentationml.presentation |
3. 백엔드는 적절하게 바이너리 스트림 파일을 반환합니다.
프로젝트에서 이러한 요구 사항이 발생했습니다. 프런트 엔드는 파일을 가져오고 백 엔드는 구문 분석하여 결과를 반환합니다. 성공하면 반환 된 데이터는 null이고 코드는 0입니다. 실패하면 Excel을 반환합니다. 이진 스트림 파일을 엑셀 파일에 저장합니다. 실패 이유가 표시되고 파일이 자동으로 다운로드됩니다.
const downloadBlob = (blob: Blob, type: string, fileName?: string) => {
const newBlob = new Blob([blob], {
type,
});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(newBlob);
link.download = fileName || '错误文件';
link.click();
};
export const FileUpload = (url: string, file: FormData): Promise => {
/** fetch 配置项 */
const params: RequestInit = {
method: 'POST',
headers: {
Authorization: '',
},
body: file,
};
return fetch(url, params).then((response) => {
if (response.status === 200 && response.body) {
return new Promise((resolve, reject) => {
const contentType = response.headers.get('content-type') || '';
if (contentType.indexOf('application/json') >= 0) {
// 返回的是 JSON 文件
response.json().then(resolve);
} else if (contentType.indexOf('application/vnd.ms-excel') >= 0) {
// 返回的是 excel 文件
response.blob().then((_blob) => {
const cd = response.headers.get('content-disposition');
const cds = cd?.split('filename=') || [];
downloadBlob(
_blob,
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8',
decodeURIComponent(cds[1]),
);
resolve();
});
} else {
// 暂时不知道是啥
reject();
}
});
}
return Promise.reject();
});
};
콘텐츠 유형에는 여러 유형이 있으며 각 유형 은 서로 다른 반환 유형에 해당합니다. 콘텐츠 유형 비교 의 전체 목록 : https://tool.oschina.net/commons/