This is an automated email from the ASF dual-hosted git repository.

jinsongzhou pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/amoro.git


The following commit(s) were added to refs/heads/master by this push:
     new b513bb124 [AMORO-3369] fix download error (#3463)
b513bb124 is described below

commit b513bb124db92beb0cd11ee0d9c55278e2a585cf
Author: xiaomo <[email protected]>
AuthorDate: Wed Mar 12 17:34:30 2025 +0800

    [AMORO-3369] fix download error (#3463)
    
    * [AMORO-3369] fix download error
    
    * chore: update file name
---
 amoro-web/src/utils/request.ts          | 83 +++++++++++++++++++++++----------
 amoro-web/src/views/catalogs/Detail.vue |  9 ++--
 2 files changed, 64 insertions(+), 28 deletions(-)

diff --git a/amoro-web/src/utils/request.ts b/amoro-web/src/utils/request.ts
index cf79e04dd..e60f22d85 100644
--- a/amoro-web/src/utils/request.ts
+++ b/amoro-web/src/utils/request.ts
@@ -104,7 +104,7 @@ instance.interceptors.response.use(
     }
     // Actively cancel the request without throwing an error
     if (axios.isCancel(error)) {
-      return new Promise(() => {}) // Returns a Promise object in the 
"pending" state, if it is not passed down, it may cause memory leaks
+      return new Promise(() => { }) // Returns a Promise object in the 
"pending" state, if it is not passed down, it may cause memory leaks
     }
     return Promise.reject(error)
   },
@@ -178,29 +178,29 @@ const request: any = function (options: 
CustomAxiosRequestConfig) {
       return Promise.reject(err) // Business custom handling errors
     })
 }
-;['get', 'delete'].forEach((method) => {
-  request[method] = function (url: string, options: CustomAxiosRequestConfig = 
{}) {
-    options = Object.assign({}, options, {
-      url,
-      method,
-    })
-    return request(options)
-  }
-})
-;['post', 'put'].forEach((method) => {
-  request[method] = function (
-    url: string,
-    data: Record<string, any> = {},
-    options: CustomAxiosRequestConfig = {},
-  ) {
-    options = Object.assign({}, options, {
-      url,
-      method,
-      data,
-    })
-    return request(options)
-  }
-})
+  ;['get', 'delete'].forEach((method) => {
+    request[method] = function (url: string, options: CustomAxiosRequestConfig 
= {}) {
+      options = Object.assign({}, options, {
+        url,
+        method,
+      })
+      return request(options)
+    }
+  })
+  ;['post', 'put'].forEach((method) => {
+    request[method] = function (
+      url: string,
+      data: Record<string, any> = {},
+      options: CustomAxiosRequestConfig = {},
+    ) {
+      options = Object.assign({}, options, {
+        url,
+        method,
+        data,
+      })
+      return request(options)
+    }
+  })
 
 /**
  * file download
@@ -224,4 +224,39 @@ export function download(url: string, _blank = true) {
   }
 }
 
+
+
+/**
+ * file download with header
+ * @param url
+ * @param _blank
+ */
+export function downloadWithHeader(url: string, fileName: string = 'download', 
_blank = true) {
+  fetch(url, {
+    headers: {
+      'X-Request-Source': 'Web'
+    }
+  })
+    .then(response => {
+      if (!response.ok) {
+        throw new Error(`HTTP error! Status: ${response.status}`)
+      }
+      return response.blob()
+    })
+    .then(blob => {
+      const fileURL = window.URL.createObjectURL(blob)
+      const link = document.createElement('a')
+      link.href = fileURL
+      link.download = fileName
+      document.body.appendChild(link)
+      link.click()
+      document.body.removeChild(link)
+      window.URL.revokeObjectURL(fileURL)
+    })
+    .catch(error => {
+      console.error('Download failed:', error)
+    })
+}
+
+
 export default request as WrapperRequest
diff --git a/amoro-web/src/views/catalogs/Detail.vue 
b/amoro-web/src/views/catalogs/Detail.vue
index 4f3d53042..0a2caac0e 100644
--- a/amoro-web/src/views/catalogs/Detail.vue
+++ b/amoro-web/src/views/catalogs/Detail.vue
@@ -33,6 +33,7 @@ import { checkCatalogStatus, delCatalog, getCatalogsSetting, 
getCatalogsTypes, s
 import type { ICatalogItem, IIOptimizeGroupItem, ILableAndValue, IMap } from 
'@/types/common.type'
 import { usePlaceholder } from '@/hooks/usePlaceholder'
 import { getResourceGroupsListAPI } from '@/services/optimize.service'
+import { downloadWithHeader } from '@/utils/request'
 
 interface IStorageConfigItem {
   label: string
@@ -606,8 +607,8 @@ function uploadFile(info: UploadChangeParam, config: { 
uploadLoading: boolean, i
     message.error((error as Error).message)
   }
 }
-function viewFileDetail(url: string) {
-  url && window.open(url)
+function viewFileDetail(url: string, fileName: string) {
+  downloadWithHeader(url, fileName)
 }
 onMounted(() => {
   getCatalogTypeOps()
@@ -724,7 +725,7 @@ onMounted(() => {
               </a-upload>
               <span
                 v-if="config.isSuccess || config.fileName" class="config-value"
-                :class="{ 'view-active': !!config.fileUrl }" 
@click="viewFileDetail(config.fileUrl)"
+                :class="{ 'view-active': !!config.fileUrl }" 
@click="viewFileDetail(config.fileUrl, config.fileName)"
               >{{ config.fileName
               }}</span>
             </a-form-item>
@@ -775,7 +776,7 @@ onMounted(() => {
               <span
                 v-if="config.isSuccess || config.fileName" class="config-value 
auth-filename"
                 :class="{ 'view-active': !!config.fileUrl }" 
:title="config.fileName"
-                @click="viewFileDetail(config.fileUrl)"
+                @click="viewFileDetail(config.fileUrl, config.fileName)"
               >{{ config.fileName }}</span>
             </a-form-item>
           </div>

Reply via email to