当前位置: 首页 > article >正文

VUE3 学习笔记(六)Post 实现文件下载(Delphi 后台)

目录

一、实现原理

二、前端代码实现

三、后端代码实现(delphi)

四、实际运行截图


正常情况下,下载文件是使用Get方法,但是,有时候有些场景是需要通过Post方法模拟实现文件下载。

 

一、实现原理

  1. 前端通过Post请求,告知后台,需要下载文件;
  2. Post时必须告知后端,需要通过blob方式返回数据,告知方法是在Post请求时设置参数:responseType: 'blob';
  3. 前端同时在请求时需要告知后台需要下载那个文件,告知方法是通过Post参数传递;
  4. 后端收到前端请求后,检查参数是否正确;
  5. 后端如果检查所有参数正确,则给前端返回文件数据流,并告知前端:content_type := 'application/octet-stream';
  6. 后端如果检查参数不正确,比如文件不存在,则需要返回JSON字符串,告知前端出现错误,告知方法为返回前端JSON字符串,并设置:content_type := 'application/json'
  7. 前端收到后台返回数据后,通过检查返回数据的类型是 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 网站的实际使用。


http://www.kler.cn/a/7235.html

相关文章:

  • LeetCode 445.两数相加 II
  • 机器学习-37-对ML的思考之机器学习发展的三个阶段和驱动AI发展三驾马车的由来
  • 大模型论文精华-AI在医疗诊断、语言学习与情绪识别等领域的最新应用进展
  • AWTK-WIDGET-WEB-VIEW 实现笔记 (1) - 难点
  • Go 语言已立足主流,编程语言排行榜24 年 11 月
  • 了解 Solon MVC 的参数注入规则
  • 【软件设计师06】数据结构与算法基础
  • 朴素贝叶斯程序
  • 【从零开始学习 UVM】12.2、UVM RAL(续更) —— RAL Model 结构
  • Linux系统【Centos7】更新内核更新软件详细教程
  • 详细介绍雷达到达角估计算法3DFFT,DBF,MUSIC,Capon的原理、对比、各自的优势
  • 【新2023Q2模拟题JAVA】华为OD机试 - 预订酒店
  • PB语言实现控制反转(IoC)
  • 【SQL开发实战技巧】系列(三十四):数仓报表场景☞如何对数据分级并行转为列
  • WangEdtior富文本编辑器
  • echarts圆形统计图与柱状图结合
  • 少儿编程 电子学会图形化编程等级考试Scratch二级真题解析(判断题)2022年12月
  • 将本地项目上传到远程仓库的步骤
  • 2.5.3 乘法
  • 【C++从0到1】14、C++中逻辑运算
  • chatGPT 又来帮忙了
  • C++ Primer第五版练习题冲冲冲
  • 卡顿优化小结
  • 计算机视觉的应用1-OCR分栏识别:两栏识别三栏识别都可以,本地部署完美拼接
  • 从零开始实现一个C++高性能服务器框架----Socket模块
  • 【分享】免梯子的GPT,玩 ChatGPT 的正确姿势