diff --git a/packages/effects/request/src/request-client/modules/downloader.test.ts b/packages/effects/request/src/request-client/modules/downloader.test.ts index 0e78b54f4..d44dcbb7b 100644 --- a/packages/effects/request/src/request-client/modules/downloader.test.ts +++ b/packages/effects/request/src/request-client/modules/downloader.test.ts @@ -31,6 +31,7 @@ describe('fileDownloader', () => { expect(result).toEqual(mockBlob); expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, { responseType: 'blob', + responseReturn: 'body', }); }); @@ -51,6 +52,7 @@ describe('fileDownloader', () => { expect(mockAxiosInstance.get).toHaveBeenCalledWith(url, { ...customConfig, responseType: 'blob', + responseReturn: 'body', }); }); diff --git a/packages/effects/request/src/request-client/modules/downloader.ts b/packages/effects/request/src/request-client/modules/downloader.ts index bf065d335..77e72c6c5 100644 --- a/packages/effects/request/src/request-client/modules/downloader.ts +++ b/packages/effects/request/src/request-client/modules/downloader.ts @@ -1,7 +1,14 @@ -import type { AxiosRequestConfig } from 'axios'; - import type { RequestClient } from '../request-client'; -import type { RequestResponse } from '../types'; +import type { RequestClientConfig } from '../types'; + +type DownloadRequestConfig = { + /** + * 定义期望获得的数据类型。 + * raw: 原始的AxiosResponse,包括headers、status等。 + * body: 只返回响应数据的BODY部分(Blob) + */ + responseReturn?: 'body' | 'raw'; +} & Omit; class FileDownloader { private client: RequestClient; @@ -9,20 +16,23 @@ class FileDownloader { constructor(client: RequestClient) { this.client = client; } - - public async download( + /** + * 下载文件 + * @param url 文件的完整链接 + * @param config 配置信息,可选。 + * @returns 如果config.responseReturn为'body',则返回Blob(默认),否则返回RequestResponse + */ + public async download( url: string, - config?: AxiosRequestConfig, - ): Promise> { - const finalConfig: AxiosRequestConfig = { + config?: DownloadRequestConfig, + ): Promise { + const finalConfig: DownloadRequestConfig = { + responseReturn: 'body', ...config, responseType: 'blob', }; - const response = await this.client.get>( - url, - finalConfig, - ); + const response = await this.client.get(url, finalConfig); return response; } diff --git a/packages/effects/request/src/request-client/modules/uploader.ts b/packages/effects/request/src/request-client/modules/uploader.ts index eed69f85c..ee5e7a23c 100644 --- a/packages/effects/request/src/request-client/modules/uploader.ts +++ b/packages/effects/request/src/request-client/modules/uploader.ts @@ -1,6 +1,5 @@ -import type { AxiosRequestConfig, AxiosResponse } from 'axios'; - import type { RequestClient } from '../request-client'; +import type { RequestClientConfig } from '../types'; class FileUploader { private client: RequestClient; @@ -9,18 +8,18 @@ class FileUploader { this.client = client; } - public async upload( + public async upload( url: string, data: Record & { file: Blob | File }, - config?: AxiosRequestConfig, - ): Promise { + config?: RequestClientConfig, + ): Promise { const formData = new FormData(); Object.entries(data).forEach(([key, value]) => { formData.append(key, value); }); - const finalConfig: AxiosRequestConfig = { + const finalConfig: RequestClientConfig = { ...config, headers: { 'Content-Type': 'multipart/form-data', diff --git a/packages/effects/request/src/request-client/preset-interceptors.ts b/packages/effects/request/src/request-client/preset-interceptors.ts index 4f327dd04..71ddc74bd 100644 --- a/packages/effects/request/src/request-client/preset-interceptors.ts +++ b/packages/effects/request/src/request-client/preset-interceptors.ts @@ -25,15 +25,15 @@ export const defaultResponseInterceptor = ({ if (config.responseReturn === 'raw') { return response; } - const code = responseData[codeField]; - if ( - status >= 200 && status < 400 && isFunction(successCode) - ? successCode(code) - : code === successCode - ) { + + if (status >= 200 && status < 400) { if (config.responseReturn === 'body') { return responseData; - } else { + } else if ( + isFunction(successCode) + ? successCode(responseData[codeField]) + : responseData[codeField] === successCode + ) { return isFunction(dataField) ? dataField(responseData) : responseData[dataField]; diff --git a/packages/effects/request/src/request-client/types.ts b/packages/effects/request/src/request-client/types.ts index e37db5c15..1abfd981e 100644 --- a/packages/effects/request/src/request-client/types.ts +++ b/packages/effects/request/src/request-client/types.ts @@ -7,9 +7,9 @@ import type { type ExtendOptions = { /** 响应数据的返回方式。 - * raw: 原始的AxiosResponse,包括headers、status等。 - * body: 返回响应数据的BODY部分。 - * data: 解构响应的BODY数据,只返回其中的data节点数据。 + * raw: 原始的AxiosResponse,包括headers、status等,不做是否成功请求的检查。 + * body: 返回响应数据的BODY部分(只会根据status检查请求是否成功,忽略对code的判断,这种情况下应由调用方检查请求是否成功)。 + * data: 解构响应的BODY数据,只返回其中的data节点数据(会检查status和code是否为成功状态)。 */ responseReturn?: 'body' | 'data' | 'raw'; }; diff --git a/playground/src/api/examples/download.ts b/playground/src/api/examples/download.ts new file mode 100644 index 000000000..0b4dcd36e --- /dev/null +++ b/playground/src/api/examples/download.ts @@ -0,0 +1,28 @@ +import type { RequestResponse } from '@vben/request'; + +import { requestClient } from '../request'; + +/** + * 下载文件,获取Blob + * @returns Blob + */ +async function downloadFile1() { + return requestClient.download( + 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', + ); +} + +/** + * 下载文件,获取完整的Response + * @returns RequestResponse + */ +async function downloadFile2() { + return requestClient.download>( + 'https://unpkg.com/@vbenjs/static-source@0.1.7/source/logo-v1.webp', + { + responseReturn: 'raw', + }, + ); +} + +export { downloadFile1, downloadFile2 }; diff --git a/playground/src/views/demos/features/file-download/index.vue b/playground/src/views/demos/features/file-download/index.vue index b4125b8a4..5342141d0 100644 --- a/playground/src/views/demos/features/file-download/index.vue +++ b/playground/src/views/demos/features/file-download/index.vue @@ -1,4 +1,6 @@