From 9edff77dcbccdb655a08569c85e10a5834d87581 Mon Sep 17 00:00:00 2001 From: lihsai0 Date: Thu, 21 Nov 2024 12:13:50 +0800 Subject: [PATCH] fix: download from s3 custom domain --- src/common/ipc-actions/download.ts | 3 ++- src/common/models/job/download-job.ts | 12 ++++++++-- .../transfer-managers/download-manager.ts | 1 + .../modules/qiniu-client/files.test.ts | 5 ++-- src/renderer/modules/qiniu-client/files.ts | 24 +++++++++++++------ src/renderer/pages/browse/files/index.tsx | 19 +++++++++++---- 6 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/common/ipc-actions/download.ts b/src/common/ipc-actions/download.ts index 321ee589..29a42a1a 100644 --- a/src/common/ipc-actions/download.ts +++ b/src/common/ipc-actions/download.ts @@ -1,5 +1,5 @@ import {NatureLanguage} from "kodo-s3-adapter-sdk/dist/uplog"; -import {Domain} from "kodo-s3-adapter-sdk/dist/adapter"; +import {Domain, UrlStyle} from "kodo-s3-adapter-sdk/dist/adapter"; import {ClientOptionsSerialized} from "@common/qiniu"; import {Status} from "@common/models/job/types"; @@ -24,6 +24,7 @@ export interface DownloadOptions { bucket: string, domain?: Domain, + urlStyle?: UrlStyle, isOverwrite: boolean, storageClasses: StorageClass[], diff --git a/src/common/models/job/download-job.ts b/src/common/models/job/download-job.ts index 1ef32552..be5b2b70 100644 --- a/src/common/models/job/download-job.ts +++ b/src/common/models/job/download-job.ts @@ -3,7 +3,7 @@ import fs, {constants as fsConstants, promises as fsPromises} from "fs"; import lodash from "lodash"; import {Downloader} from "kodo-s3-adapter-sdk"; -import {Adapter, Domain, ObjectHeader, StorageClass} from "kodo-s3-adapter-sdk/dist/adapter"; +import {Adapter, Domain, ObjectHeader, StorageClass, UrlStyle} from "kodo-s3-adapter-sdk/dist/adapter"; import {NatureLanguage} from "kodo-s3-adapter-sdk/dist/uplog"; import {ClientOptions, createQiniuClient} from "@common/qiniu"; @@ -36,7 +36,8 @@ interface DownloadOptions { interface OptionalOptions extends DownloadOptions { id: string, - domain?: Domain, + domain: Domain | undefined, + urlStyle: UrlStyle | undefined, status: Status, message: string, @@ -58,6 +59,8 @@ type Options = RequiredOptions & Partial const DEFAULT_OPTIONS: OptionalOptions = { id: "", + domain: undefined, + urlStyle: undefined, multipartDownloadThreshold: 100, multipartDownloadSize: 8, @@ -86,6 +89,7 @@ type PersistInfo = { from: RequiredOptions["from"], backendMode: RequiredOptions["clientOptions"]["backendMode"], domain: OptionalOptions["domain"], + urlStyle: OptionalOptions["urlStyle"], prog: OptionalOptions["prog"], status: Exclude, message: OptionalOptions["message"], @@ -112,6 +116,8 @@ export default class DownloadJob extends TransferJob { ): DownloadJob { return new DownloadJob({ id, + domain: persistInfo.domain, + urlStyle: persistInfo.urlStyle, status: persistInfo.status, message: persistInfo.message, @@ -213,6 +219,7 @@ export default class DownloadJob extends TransferJob { to: this.options.to, from: this.options.from, domain: this.options.domain, + urlStyle: this.options.urlStyle, storageClasses: this.options.storageClasses, backendMode: this.options.clientOptions.backendMode, @@ -297,6 +304,7 @@ export default class DownloadJob extends TransferJob { this.tempFilePath, this.options.domain, { + urlStyle: this.options.urlStyle, recoveredFrom: this.prog.resumable ? this.prog.loaded : 0, diff --git a/src/main/transfer-managers/download-manager.ts b/src/main/transfer-managers/download-manager.ts index 7bf67f86..f0c0e355 100644 --- a/src/main/transfer-managers/download-manager.ts +++ b/src/main/transfer-managers/download-manager.ts @@ -293,6 +293,7 @@ export default class DownloadManager extends TransferManager { mockDataKey, undefined, 10, - name === "S3" ? "path" : "bucketEndpoint", + name === "S3" ? UrlStyle.Path : UrlStyle.BucketEndpoint, mockOpt, ); expect(QiniuClientCommon.getDefaultClient).toBeCalledTimes(1); diff --git a/src/renderer/modules/qiniu-client/files.ts b/src/renderer/modules/qiniu-client/files.ts index c70ac10b..c8e34acf 100644 --- a/src/renderer/modules/qiniu-client/files.ts +++ b/src/renderer/modules/qiniu-client/files.ts @@ -1,6 +1,15 @@ import * as qiniuPathConvertor from "qiniu-path/dist/src/convert"; import { Path as QiniuPath } from "qiniu-path/dist/src/path"; -import { Adapter, Domain, FrozenInfo, ObjectInfo, PartialObjectError, StorageClass, TransferObject } from 'kodo-s3-adapter-sdk/dist/adapter' +import { + Adapter, + Domain, + FrozenInfo, + ObjectInfo, + PartialObjectError, + StorageClass, + TransferObject, + UrlStyle, +} from 'kodo-s3-adapter-sdk/dist/adapter' import {BackendMode} from "@common/qiniu"; import Duration from "@common/const/duration"; @@ -333,14 +342,16 @@ export function getStyleForSignature({ domain: Domain | undefined, preferBackendMode: BackendMode | undefined, currentEndpointType: EndpointType, -}): "path" | "virtualHost" | "bucketEndpoint" { +}): UrlStyle { if (domain?.apiScope === BackendMode.S3) { - return "bucketEndpoint"; + return UrlStyle.BucketEndpoint; } else if (!domain || preferBackendMode === BackendMode.S3) { // some private cloud not support wildcard domain name resolving - return currentEndpointType === EndpointType.Public ? "virtualHost" : "path"; + return currentEndpointType === EndpointType.Public + ? UrlStyle.VirtualHost + : UrlStyle.Path; } else { - return "bucketEndpoint"; + return UrlStyle.BucketEndpoint; } } @@ -350,7 +361,7 @@ export async function signatureUrl( key: QiniuPath | string, domain: Domain | undefined, expires: number, // seconds - style: "path" | "virtualHost" | "bucketEndpoint", + style: UrlStyle, opt: GetAdapterOptionParam, ): Promise { const deadline = new Date(); @@ -969,4 +980,3 @@ export async function signatureUrls( return results; } } - diff --git a/src/renderer/pages/browse/files/index.tsx b/src/renderer/pages/browse/files/index.tsx index 6295965b..58cfe190 100644 --- a/src/renderer/pages/browse/files/index.tsx +++ b/src/renderer/pages/browse/files/index.tsx @@ -14,8 +14,8 @@ import {useAuth} from "@renderer/modules/auth"; import {KodoNavigator, useKodoNavigator} from "@renderer/modules/kodo-address"; import {ContentViewStyle, appPreferences, useEndpointConfig} from "@renderer/modules/user-config-store"; -import {BucketItem, FileItem, isAccelerateUploadingAvailable} from "@renderer/modules/qiniu-client"; -import {DomainAdapter, useLoadDomains, useLoadFiles} from "@renderer/modules/qiniu-client-hooks"; +import {BucketItem, FileItem, getStyleForSignature, isAccelerateUploadingAvailable} from "@renderer/modules/qiniu-client"; +import {DomainAdapter, NON_OWNED_DOMAIN, useLoadDomains, useLoadFiles} from "@renderer/modules/qiniu-client-hooks"; import ipcDownloadManager from "@renderer/modules/electron-ipc-manages/ipc-download-manager"; import * as AuditLog from "@renderer/modules/audit-log"; import {useFileOperation} from "@renderer/modules/file-operation"; @@ -38,7 +38,10 @@ interface FilesProps { const Files: React.FC = (props) => { const {currentLanguage, translate} = useI18n(); const {currentUser, shareSession} = useAuth(); - const {bucketGrantedPermission} = useFileOperation(); + const { + bucketPreferBackendMode: preferBackendMode, + bucketGrantedPermission, + } = useFileOperation(); const { state: appPreferencesState, @@ -350,13 +353,21 @@ const Files: React.FC = (props) => { to: destDirectoryPath, from: remoteObjects.map(i => i.key), }); + const domain = selectedDomain.name === NON_OWNED_DOMAIN.name + ? undefined + : selectedDomain; ipcDownloadManager.addJobs({ remoteObjects, destPath: destDirectoryPath, downloadOptions: { region: currentRegion.s3Id, bucket: currentBucket.name, - domain: selectedDomain, + domain: domain, + urlStyle: getStyleForSignature({ + domain: domain, + preferBackendMode, + currentEndpointType: currentUser.endpointType, + }), isOverwrite: appPreferencesData.overwriteDownloadEnabled, storageClasses: currentRegion.storageClasses, // userNatureLanguage needs mid-dash but i18n using lo_dash