任务中心示例及浏览器强制高效下载实践

article/2025/6/12 9:18:24

1. 效果展示

任务中心
这里的进度展示,可以通过我们之前讲到的Vue3实现类ChatGPT聊天式流式输出(vue-sse实现) SSE技术实现,比如用户点击全量下载时,后台需要将PDF文件打包为ZIP文件,由于量较大,需要展示进度,用户点击全量下载后后可到任务中心查看进度。对于任务中心的下载我们如果用浏览器自带下载功能,可以如下

2. 浏览器强制高效下载

@Overridepublic void downloadStream(String fileId, HttpServletResponse response) {Path filePath = Paths.get(Constant.FILE_PREFIX + fileId);String fileName = filePath.getFileName().toString();try {if (!Files.exists(filePath)) {response.setStatus(HttpServletResponse.SC_NOT_FOUND);throw new RuntimeException("File not found: " + filePath);}String contentType = Files.probeContentType(filePath);response.setContentType(contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM_VALUE);response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");response.setContentLengthLong(Files.size(filePath));String acceptEncoding = response.getHeader("Accept-Encoding");if (acceptEncoding != null && acceptEncoding.contains("gzip")) {response.setHeader("Content-Encoding", "gzip");try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ);GZIPOutputStream gzipOut = new GZIPOutputStream(response.getOutputStream())) {channel.transferTo(0, channel.size(), Channels.newChannel(gzipOut));}} else {try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ);OutputStream out = new BufferedOutputStream(response.getOutputStream(), BUFFER_SIZE)) {channel.transferTo(0, channel.size(), Channels.newChannel(out));}}} catch (IOException e) {response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);throw new RuntimeException("Failed to download file: " + e.getMessage(), e);}}

3. 任务中心示例

<template><div class="task"><el-row style="margin: 20px"><el-table :data="dataList" @current-change="handleCurrentChange" border highlight-current-row :header-cell-style="setRowClass" :cell-style="{ textAlign: 'center' }" stripe><el-table-column prop="taskId" label="任务编号"> </el-table-column><el-table-column prop="taskName" label="任务名称"></el-table-column><el-table-column prop="progress" label="任务进度"><template #default="scope"><el-progress :percentage="scope.row.progress" :color="progressColor"/></template></el-table-column><el-table-column prop="statusDesc" label="任务状态"></el-table-column><el-table-column prop="createUser" label="创建人"></el-table-column><el-table-column prop="createTime" label="创建日期"><template v-slot="scope">{{ $formatDate(scope.row.createTime, 'yyyy-MM-dd') }}</template></el-table-column><el-table-column prop="operate" align="center" label="操作" width="170px"><template v-slot="scope"><el-button type="primary" size="small" :icon="Download"@click="handleDownload(scope.row)">下载</el-button></template></el-table-column></el-table></el-row><el-row style="float:right; margin-top: 15px;"><paginationbackground@pagination="updatePageInfo":page-size="page.pageSize"v-model:current-page="page.pageNumber":total="page.total"></pagination></el-row></div>
</template>
<script>
import {Delete, Download, Edit, Plus, Search} from "@element-plus/icons-vue";
import Pagination from "@/components/pagination/Index.vue";
import baseUrl from "../../util/baseUrl";export default {name: 'task',computed: {Delete() {return Delete},Edit() {return Edit},Plus() {return Plus},Search() {return Search},Download() {return Download},},components: {Pagination},data() {return {tree: [],dataList: [],// 查询条件query: {username: '',account: ''},// 选中树节点信息currentTreeNode: '',// 表格选中行信息currentRow: '',visible: {add: false,edit: false},progressColor: [{color: '#f56c6c', percentage: 20},{color: '#e6a23c', percentage: 40},{color: '#5cb87a', percentage: 60},{color: '#1989fa', percentage: 80},{color: '#6f7ad3', percentage: 100},],page: {pageNumber: 1,pageSize: 10,total: 10},importCustomData: false,fileUpload: {label: '',fileList: [],},url: ''}},created() {// 无需跨域,否则无法接收消息, 这个原因浪费我好多时间if (process.env.NODE_ENV === 'development') {this.url = 'http://127.0.0.1:8080/sse/subscribe?token=' + this.$store.getters.token} else {this.url = 'https://api-uat.sfxs.com/sse/subscribe?token=' + this.$store.getters.token}this.listData()},mounted() {this.connect()},methods: {connect () {// create the client with the user's configconst self = thislet client = self.$sse.create({url: this.url,includeCredentials: false})client.on('message', (data) => {// eslint-disable-next-line no-emptyif (data === '<SSE_START>') {} else {const ret = JSON.parse(data)self.dataList.forEach((item, index, arr) => {if (ret['taskId'] === item['taskId']) {// 更细进度与状态self.dataList[index]['progress'] = ret['progress']self.dataList[index]['statusDesc'] = ret['statusDesc']}})}})client.on('error', () => { // eslint-disable-lineconsole.log('[error] disconnected, automatically re-attempting connection', 'system')})// and finally -- try to connect!client.connect() // eslint-disable-line.then(() => {console.log('[info] connected', 'system')}).catch(() => {console.log('[error] failed to connect', 'system')})},listData() {const self = thisself.$http.post('/task/list', self.query, 'apiUrl').then(res => {self.dataList = res.recordsself.page.total = res.total})},handleCurrentChange (val) {if (val) {this.currentRow = val}},setRowClass () {return {background: '#F3F3F3', textAlign: 'center', color: 'black'}},updatePageInfo (data) {const self = thisself.page.pageNumber = data.pageNumberself.page.pageSize = data.pageSizeself.listData()},handleDownload(row) {const self = thisself.visible.add = truewindow.open(baseUrl.apiUrl + '/download/stream?fileId=' + row.url, "_blank");}}
}
</script>

http://www.hkcw.cn/article/BjSWYVufel.shtml

相关文章

危地马拉发现2800多年前玛雅城市遗址

var chan_v_w = 960,chan_v_h = 540,chan_v_p = https://mts-audio.huawangzhixun.com/image/20250601/news/5512b3f2-c97c-4299-b34c-8f5e57413ca6.jpg,chan_v_s = https://vmts.china.com/api/video/onaliyun/query?id=3101125&ttype=mp4;据危地马拉媒体5月30日报道,危…

姜老师MBTI课程:4条轴线的总结

文稿&#xff1a; 第一点是有的时候真的分不清到底是N还是S而且会跟自己的朋友去争论他这个表现到底是J还是P说不清。感觉有些案例姜老师讲的也是既有J又有P最后娶了一个什么&#xff1f;能不能够给我们提一些非常精准的标准&#xff0c;帮我们来做尽量精准的判断。好&#xff…

限流算法相关知识点

目录 固定窗口算法滑动窗口算法漏桶算法令牌桶算法Sentinel限流例子 固定窗口算法 固定窗口算法的实现相对简单。系统维护一个计数器&#xff0c;每当请求到来时&#xff0c;计数器加一。当时间窗口结束时&#xff0c;计数器清零。如果在一个时间窗口内请求数量超过了预设的阈…

第N个泰波那契数列 --- 动态规划

目录 一&#xff1a;题目 二&#xff1a;算法原理 三&#xff1a;代码实现 一&#xff1a;题目 题目链接&#xff1a;1137. 第 N 个泰波那契数 - 力扣&#xff08;LeetCode&#xff09; 二&#xff1a;算法原理 三&#xff1a;代码实现 class Solution { public:int trib…

【题解-洛谷】P3467 [POI 2008] PLA-Postering

题目&#xff1a;P3467 [POI 2008] PLA-Postering 题目描述 Byteburg 城市的东区所有建筑都是按照旧式建筑风格建造的&#xff1a;它们一个接一个地紧挨在一起&#xff0c;中间没有任何间隔。它们从东到西排列&#xff0c;形成了一排高度各异的建筑长廊。 Byteburg 的市长 B…

樊振东加盟 德国俱乐部:他主动的 新挑战迎期待

当樊振东在社交媒体上发布观赛欧冠的照片时,另一条消息也震惊了乒乓球圈。6月1日,德国乒乓球甲级联赛FC萨尔布吕肯乒乓球俱乐部宣布,奥运冠军樊振东将加盟球队。樊振东表示,他非常期待在萨尔布吕肯和德甲的新挑战,体验新的环境,并与球队一起赢得更多胜利。球队体育总监埃…

雷军祝儿童节快乐 分享健身照送祝福

6月1日,小米科技创始人、董事长雷军在微博分享了健身打卡照片,并向小朋友送上儿童节祝福,祝所有小朋友都有一个快乐的童年。他还附上了一张富有童趣的AI图片,图片中“Q版雷军”坐在旋转木马上,双手紧握拳头,呈现出加油打气的动作。责任编辑:zx0176

Vue ①-实例 || 指令

Vue Vue 是一个构建用户界面的渐进式框架&#xff0c;也就是 UI 框架。 创建 Vue 实例 创建 Vue实例&#xff0c;初始化渲染&#xff1a; 准备容器&#xff08;Vue所管理的范围&#xff09;引包&#xff08;开发版本包 / 生产版本包&#xff08;官网找&#xff09;&#xf…

尚硅谷redis7 93-97 springboot整合reids之总体概述

93 springboot整合reids之总体概述 总体概述 jedis-lettuce-RedisTemplate三者的联系 名称类型作用描述和其它的关系JedisRedis 客户端早期主流的 Java Redis 客户端&#xff0c;基于阻塞 I/O&#xff0c;同步操作可作为 RedisTemplate 的底层连接实现LettuceRedis 客户端基…

两个女首富杠起来了 医美巨头争议不断

巨子生物和华熙生物近期陷入了各自的尴尬境地。市值745亿港元的医美新贵巨子生物因一位博主的视频面临了广泛的造假质疑。与此同时,业绩下滑的玻尿酸巨头华熙生物发文痛斥券商研报“踩一捧一”,试图证明玻尿酸还未过时,但显得有些无力。一些曾鼓吹重组胶原蛋白和巨子生物的券…

屈原的老家端午要过三次 三次端午的独特庆祝

端午节作为我国最古老的节日之一,在众多习俗中,以纪念屈原影响最为广泛。屈原出生于战国时期的湖北秭归,当地不仅保留着典型的屈原故里端午习俗,还有“端午比年大”的说法。在屈原的家乡湖北秭归乐平里,这里位于山谷中央,四面群山环抱,不远处是长江的支流香溪河。古籍记…

张若昀一家三口现身伦敦过六一 异国街头温馨同游

6月1日,张若昀和唐艺昕带着女儿在伦敦游玩时被网友偶遇。一家三口走在异国街头,画面十分温馨。张若昀推着婴儿车,尽显父爱;唐艺昕穿着黑色衣服,皮肤白皙气质出众;女儿坐在小车上乖巧可爱。明星们在国内逛街容易受到关注,因此他们更倾向于在国外享受私人时光。这次张若昀…

黄石公园车祸致5华人身亡司机涉酒驾 肇事司机酒精含量超标两倍

美国警方于5月30日透露,5月初在黄石国家公园附近发生的一起导致7人死亡的交通事故中,肇事皮卡司机的血液酒精含量超过法定驾驶限值的两倍。这起事故发生在5月1日晚,地点位于美国爱达荷州黄石国家公园附近。事故造成7人死亡、多人受伤。中国驻旧金山总领馆在5月2日确认,死者…

叶童回应与陈丽君合作 虚实共生演绎许仙

5月31日晚,陈丽君与叶童在央视端午晚会上同框,共唱戏歌《浮生一白》。叶童随后在微博发文表示,这次与陈丽君的合作非常特别,虚实共生,共同演绎了这首歌曲。陈丽君也转发了这条微博,表达了与叶童老师合作的喜悦。叶童曾在经典剧作《新白娘子传奇》中成功塑造许仙一角。此次…

AI时代,大公司如何创新?

大模型时代&#xff0c;以OpenAI&#xff0c;DeepSeek为首的一些创业公司迅速崛起&#xff0c;微软、苹果、谷歌、华为等大公司跟他们相比&#xff0c;明显迟缓。所以自己最近一直在思考和观察创业公司的创新模式&#xff0c;看看有什么启发。 “强大的物种追求繁殖能力强。”是…

混沌映射(Chaotic Map)

一.定义 混沌映射是指一类具有混沌行为的离散时间非线性动力系统&#xff0c;通常由递推公式定义。其数学形式为 &#xff0c;其中 f 是非线性函数&#xff0c;θ 为参数。它们以简单的数学规则生成复杂的、看似随机的轨迹&#xff0c;是非线性动力学和混沌理论的重要研究对象…

Python训练营打卡Day41

DAY 41 简单CNN 知识回顾 1.数据增强 2.卷积神经网络定义的写法 3.batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据 4.特征图&#xff1a;只有卷积操作输出的才叫特征图 5.调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 输入…

Java中的继承

1.继承的语法 2.如何访问父类的成员变量和方法 3.super的使用 4.继承中的构造函数 5.父类和子类代码块调用顺序 6.protected的使用 7.final的使用 1.继承的语法 在日常生活的&#xff0c;我们一听到继承&#xff0c;就会想到继承家里的财产&#xff0c;所以继承的本质就…

2022年 能源统计年鉴Excel电子版

2022年 能源统计年鉴Excel电子版.ziphttps://download.csdn.net/download/2401_84585615/89772876 https://download.csdn.net/download/2401_84585615/89772876 《中国能源统计年鉴2022》是由国家统计局能源统计司主编的权威性资料书&#xff0c;全面反映了中国能源建设、生产…

牛客小白月赛117

依旧掉分场, 疯狂wa, 感觉越打越菜了.... A. 好字符串 题目描述 给你一个长度为 n 的字符串 s&#xff0c;如果一个小写字母为好字符&#xff0c;当且仅当该小写字母对应的大写字母和它同时在字符串 s 中出现 或者 同时不在字符串 s 中出现&#xff1b;而如果一个字符串为好…