|
@@ -9,6 +9,12 @@
|
|
|
</div>
|
|
|
<div v-if="toolButton" class="header-button-ri">
|
|
|
<slot name="toolButton">
|
|
|
+ <el-progress :stroke-width="10" :percentage="downloadObj.percentage" v-if="downloadObj.downloading">
|
|
|
+ <template #default="{ percentage }">
|
|
|
+ <span class="font14">{{ percentage }}%</span>
|
|
|
+ <span class="font14">导出进度</span>
|
|
|
+ </template>
|
|
|
+ </el-progress>
|
|
|
<el-button v-if="showToolButton('refresh')" circle @click="onRefresh" title="刷新表格">
|
|
|
<SvgIcon name="ele-Refresh" />
|
|
|
</el-button>
|
|
@@ -21,7 +27,7 @@
|
|
|
<el-button v-if="showToolButton('exportAll') && columns.length" circle @click="exportAll" title="导出全部">
|
|
|
<SvgIcon name="iconfont icon-export" />
|
|
|
</el-button>
|
|
|
- </slot>
|
|
|
+ </slot>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 表格主体 -->
|
|
@@ -328,6 +334,103 @@ watch(
|
|
|
clearSelection();
|
|
|
}
|
|
|
);
|
|
|
+
|
|
|
+//下载逻辑
|
|
|
+const downloadObj = reactive({
|
|
|
+ fileName: '',
|
|
|
+ downloading: false,
|
|
|
+ range: 0,
|
|
|
+ fileBlob: [],
|
|
|
+ percentage: 0,
|
|
|
+})
|
|
|
+
|
|
|
+const download = async () => {
|
|
|
+ downloadObj.fileBlob = []
|
|
|
+ downloadObj.downloading = true
|
|
|
+ downloadObj.range = 0 //文件总大小
|
|
|
+ downloadObj.percentage = 0 //下载进度
|
|
|
+ const params = {
|
|
|
+ md5: '7343784583fsdufhusdfgsudfe8934',
|
|
|
+ }
|
|
|
+ const chunkSize = 5 * 1024 * 1024
|
|
|
+
|
|
|
+ //第一次调接口获取到响应头的content-range,文件总大小,用于计算下载切割
|
|
|
+ const config = {
|
|
|
+ headers: {
|
|
|
+ Range: `bytes=0-${chunkSize}`,
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ const data = await downLoadbyPiece(params, config)
|
|
|
+
|
|
|
+ //获取文件总大小
|
|
|
+ const arr = data.headers['content-range'].split('/')
|
|
|
+ downloadObj.range = Number(arr[1])
|
|
|
+ //存储每片文件流
|
|
|
+ downloadObj.fileBlob.push(data.data)
|
|
|
+ //获取文件名称
|
|
|
+ let fileName = ''
|
|
|
+ let cd = data.headers['content-disposition']
|
|
|
+ if (cd) {
|
|
|
+ let index = cd.lastIndexOf('=')
|
|
|
+ fileName = decodeURI(cd.substring(index + 1, cd.length))
|
|
|
+ }
|
|
|
+
|
|
|
+ await chunkUpload(params, fileName, chunkSize)
|
|
|
+}
|
|
|
+
|
|
|
+//拿到文件总大小downloadObj.range,计算分为多少都段下载
|
|
|
+const chunkUpload = async (params, fileName, chunkSize) => {
|
|
|
+ //获取分段下载的数组
|
|
|
+ let chunkList = []
|
|
|
+ function chunkPush(page = 1) {
|
|
|
+ chunkList.push((page - 1) * chunkSize)
|
|
|
+ if (page * chunkSize < downloadObj.range) {
|
|
|
+ chunkPush(page + 1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ chunkPush()
|
|
|
+
|
|
|
+ //加上文件大小在最后一位
|
|
|
+ chunkList.push(downloadObj.range)
|
|
|
+ console.log(chunkList, 'chunkList')
|
|
|
+ //分段组合传参格式处理 0-1024 1024-2048
|
|
|
+ let uploadRange = []
|
|
|
+ chunkList.forEach((item, i) => {
|
|
|
+ if (i == chunkList.length - 1) return
|
|
|
+
|
|
|
+ uploadRange.push(`${chunkList[i]}-${chunkList[i + 1]}`)
|
|
|
+ })
|
|
|
+ console.log(uploadRange, 'uploadRang')
|
|
|
+ for (let index = 0; index < uploadRange.length; index++) {
|
|
|
+ //第一次调接口已经传过了第一组,从第二位开始
|
|
|
+ if (index > 0) {
|
|
|
+ const config = {
|
|
|
+ headers: {
|
|
|
+ Range: `bytes=${uploadRange[index]}`,
|
|
|
+ },
|
|
|
+ }
|
|
|
+ const data = await downLoadbyPiece(params, config)
|
|
|
+ //计算下载进度
|
|
|
+ downloadObj.percentage = Math.floor(((index + 1) / uploadRange.length) * 100)
|
|
|
+ emit('getDownloadpercent', downloadObj.percentage)
|
|
|
+ //存储每一片文件流
|
|
|
+ downloadObj.fileBlob.push(data.data)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //合并
|
|
|
+ const blob = new Blob(downloadObj.fileBlob, {
|
|
|
+ type: downloadObj.fileBlob[0].type,
|
|
|
+ })
|
|
|
+ downloadObj.downloading = false
|
|
|
+ //下载
|
|
|
+ const link = document.createElement('a')
|
|
|
+ const URL = window.URL || window.webkitURL;
|
|
|
+ link.href = URL.createObjectURL(blob)
|
|
|
+ link.download = fileName
|
|
|
+ link.click()
|
|
|
+ URL.revokeObjectURL(link.href)
|
|
|
+}
|
|
|
// 暴露给父组件的参数和方法 (外部需要什么,都可以从这里暴露出去)
|
|
|
defineExpose({
|
|
|
element: tableRef,
|