VUE3 学习笔记(六)Post 实现文件下载(Delphi 后台)
目录
一、实现原理
二、前端代码实现
三、后端代码实现(delphi)
四、实际运行截图
正常情况下,下载文件是使用Get方法,但是,有时候有些场景是需要通过Post方法模拟实现文件下载。
一、实现原理
- 前端通过Post请求,告知后台,需要下载文件;
- Post时必须告知后端,需要通过blob方式返回数据,告知方法是在Post请求时设置参数:responseType: 'blob';
- 前端同时在请求时需要告知后台需要下载那个文件,告知方法是通过Post参数传递;
- 后端收到前端请求后,检查参数是否正确;
- 后端如果检查所有参数正确,则给前端返回文件数据流,并告知前端:content_type := 'application/octet-stream';
- 后端如果检查参数不正确,比如文件不存在,则需要返回JSON字符串,告知前端出现错误,告知方法为返回前端JSON字符串,并设置:content_type := 'application/json';
- 前端收到后台返回数据后,通过检查返回数据的类型是 application/octet-stream 还是 application/json ,如果是前者,则直接模拟文件下载,否则显示文本信息。
二、前端代码实现
// 通过 HTTP_POST 下载文件
// 本函数访问后台 命令码为/11,访问数据库 SYS_Download
// Title:表示下载到本地的文件名称
// FileLink: 表示在数据库中存放的Url路径,后台通过这个参数确定文件位置
// ID:表示在 后台数据库中的表 SYS_Download 中的ID
// url: 表示执行的命令码 11 表示通过Post 下载文件
// 返回:
// 如果返回 blob 数据,则直接启动下载,如果返回的是 text 则显示错误信息
function HTTP_DOWNLOAD(Title: string,FileLink: string,ID: number,url: string='/11'){
//构造请求的数据
const data = {ID,FileLink,Title}
//启动axios请求,注意必须是 blob类型
axios.post(url,data,{responseType: 'blob'})
.then(
async res => {
// console.log(res);
const blob = res.data;
// console.log(blob)
if(blob.type==="application/octet-stream"){
const download_url = window.URL.createObjectURL(blob); //数据流作为下载的源
const eleLink = document.createElement('a'); //创建一个a标签
eleLink.href = download_url //下载的文件连接,实际就是下载的数据流
eleLink.download = Title //下载的文件名称
document.body.appendChild(eleLink)
eleLink.click() //模拟下载文件
window.URL.revokeObjectURL(download_url)
}
else{
// blob.text().then((text: string) => {console.log(text)});
const text: string = await blob.text(); //接收到的是字符串
const data = JSON.parse(text); //将字符串转换为 JSON
console.log(data)
myAlert(data.errmsg + '(' + data.errcode + ')','错误',"error")
}
}
)
.catch(error => {
myAlert('下载资源出现错误(' + error + ')','提示',"warning")
})
}
注意:myAlert 是封装的一个提示框,这个可以自行处理!
三、后端代码实现(delphi)
//4. 11 下载文件,入口参数:{ID: integer,FileLink: string,Title: string} 出口参数:
procedure do_Downlload_File(RequestData : string; var content_type,ResponseData: string ;var ResponseDataStream: TStream);
var
jo : TJSONObject;
FileName : string;
ID ,size : Integer;
FileStream: TFileStream;
errmsg : string;
FileLink : string;
Title : string;
begin
//1. 首先检查参数是否正常
jo := TJSONObject.ParseJSONValue(RequestData) as TJSONObject;
if jo = nil then
begin
content_type := 'application/json'; //表示返回的是一个JSON
errmsg := '请求参数不是合法的JSON: ' + TNetEncoding.URL.Decode(RequestData);
ResponseData := Return_ERRORMSG('E11',errmsg);
Putlog_GUI(errmsg,clred);
Exit;
end;
try
FileLink := jo.S['FileLink'];
if FileLink = '' then
begin
content_type := 'application/json'; //表示返回的是一个JSON
errmsg := '请求参数不是合法的JSON: ' + TNetEncoding.URL.Decode(RequestData);
ResponseData := Return_ERRORMSG('E11_1',errmsg);
Putlog_GUI(errmsg,clred);
Exit;
end;
ID := jo.I['ID'];
if ID = 0 then
begin
content_type := 'application/json'; //表示返回的是一个JSON
errmsg := '请求参数不是合法的JSON: ' + TNetEncoding.URL.Decode(RequestData);
ResponseData := Return_ERRORMSG('E11_2',errmsg);
Putlog_GUI(errmsg,clred);
Exit;
end;
Title := jo.S['Title'];
finally
jo.Free;
end;
//构建实际的文件路径
FileName := G_Static_RootDir.Replace('dist','') + FileLink.Replace('/','\');
//2. 判断文件是否存在
if not FileExists(FileName) then
begin
content_type := 'application/json'; //表示返回的是一个JSON
ResponseData := Return_ERRORMSG('E11','资源: ' + Title + ' 丢失了');
Putlog_GUI('资源: ' + Title + ' 丢失了',clred);
Exit;
end;
//3. 准备下载数据
FileStream := TFileStream.Create(FileName, fmOpenRead + fmShareDenyNone); //共享 打开文件
FileStream.Position := 0;
Size := FileStream.Size;
try
ResponseDataStream.Position := 0;
ResponseDataStream.CopyFrom(FileStream);
finally
FileStream.Free;
end;
//增加一个下载返回类型
content_type := 'application/octet-stream'; //表示返回的是一个stream
Putlog_GUI('下载资源完成: ' + FileName + '(' + Size.ToString + ')',clGreen);
//增加一个下载点击
Add_Hits('SYS_Download',ID,1);
end;
四、实际运行截图
资源不存在信息:
模拟下载完成信息
本文介绍的方法就是 http://www.abitsoft.com 网站的实际使用。