Skip to content

Commit 172976c

Browse files
committed
fix: download from s3 custom domain
1 parent 1133d2a commit 172976c

File tree

8 files changed

+73
-24
lines changed

8 files changed

+73
-24
lines changed

src/common/ipc-actions/download.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {NatureLanguage} from "kodo-s3-adapter-sdk/dist/uplog";
2-
import {Domain} from "kodo-s3-adapter-sdk/dist/adapter";
2+
import {Domain, UrlStyle} from "kodo-s3-adapter-sdk/dist/adapter";
33

44
import {ClientOptionsSerialized} from "@common/qiniu";
55
import {Status} from "@common/models/job/types";
@@ -24,6 +24,7 @@ export interface DownloadOptions {
2424
bucket: string,
2525

2626
domain?: Domain,
27+
urlStyle?: UrlStyle,
2728

2829
isOverwrite: boolean,
2930
storageClasses: StorageClass[],

src/common/models/job/download-job.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import fs, {constants as fsConstants, promises as fsPromises} from "fs";
33

44
import lodash from "lodash";
55
import {Downloader} from "kodo-s3-adapter-sdk";
6-
import {Adapter, Domain, ObjectHeader, StorageClass} from "kodo-s3-adapter-sdk/dist/adapter";
6+
import {Adapter, Domain, ObjectHeader, StorageClass, UrlStyle} from "kodo-s3-adapter-sdk/dist/adapter";
77
import {NatureLanguage} from "kodo-s3-adapter-sdk/dist/uplog";
88

99
import {ClientOptions, createQiniuClient} from "@common/qiniu";
@@ -36,7 +36,8 @@ interface DownloadOptions {
3636

3737
interface OptionalOptions extends DownloadOptions {
3838
id: string,
39-
domain?: Domain,
39+
domain: Domain | undefined,
40+
urlStyle: UrlStyle | undefined,
4041

4142
status: Status,
4243
message: string,
@@ -58,6 +59,8 @@ type Options = RequiredOptions & Partial<OptionalOptions>
5859

5960
const DEFAULT_OPTIONS: OptionalOptions = {
6061
id: "",
62+
domain: undefined,
63+
urlStyle: undefined,
6164

6265
multipartDownloadThreshold: 100,
6366
multipartDownloadSize: 8,
@@ -86,6 +89,7 @@ type PersistInfo = {
8689
from: RequiredOptions["from"],
8790
backendMode: RequiredOptions["clientOptions"]["backendMode"],
8891
domain: OptionalOptions["domain"],
92+
urlStyle: OptionalOptions["urlStyle"],
8993
prog: OptionalOptions["prog"],
9094
status: Exclude<OptionalOptions["status"], Status.Waiting | Status.Running>,
9195
message: OptionalOptions["message"],
@@ -112,6 +116,8 @@ export default class DownloadJob extends TransferJob {
112116
): DownloadJob {
113117
return new DownloadJob({
114118
id,
119+
domain: persistInfo.domain,
120+
urlStyle: persistInfo.urlStyle,
115121
status: persistInfo.status,
116122
message: persistInfo.message,
117123

@@ -213,6 +219,7 @@ export default class DownloadJob extends TransferJob {
213219
to: this.options.to,
214220
from: this.options.from,
215221
domain: this.options.domain,
222+
urlStyle: this.options.urlStyle,
216223
storageClasses: this.options.storageClasses,
217224
backendMode: this.options.clientOptions.backendMode,
218225

@@ -297,6 +304,7 @@ export default class DownloadJob extends TransferJob {
297304
this.tempFilePath,
298305
this.options.domain,
299306
{
307+
urlStyle: this.options.urlStyle,
300308
recoveredFrom: this.prog.resumable
301309
? this.prog.loaded
302310
: 0,

src/main/transfer-managers/download-manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ export default class DownloadManager extends TransferManager<DownloadJob, Config
293293
overwrite: downloadOptions.isOverwrite,
294294
region: downloadOptions.region,
295295
domain: downloadOptions.domain,
296+
urlStyle: downloadOptions.urlStyle,
296297

297298
multipartDownloadThreshold: this.config.multipartThreshold,
298299
multipartDownloadSize: this.config.multipartSize,

src/renderer/components/modals/preview-file/file-content/code-content.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {BackendMode} from "@common/qiniu"
77

88
import {useI18n} from "@renderer/modules/i18n";
99
import {useAuth} from "@renderer/modules/auth";
10-
import {getContent, saveContent} from "@renderer/modules/qiniu-client";
10+
import {getContent, saveContent, getStyleForSignature} from "@renderer/modules/qiniu-client";
1111
import {DomainAdapter, NON_OWNED_DOMAIN} from "@renderer/modules/qiniu-client-hooks";
1212
import {DiffView, EditorView} from "@renderer/modules/codemirror";
13+
import {useFileOperation} from "@renderer/modules/file-operation";
1314

1415
import LoadingHolder from "@renderer/components/loading-holder";
1516

@@ -34,6 +35,7 @@ const CodeContent: React.FC<CodeContentProps> = ({
3435
}) => {
3536
const {translate} = useI18n();
3637
const {currentUser} = useAuth();
38+
const {bucketPreferBackendMode: preferBackendMode} = useFileOperation();
3739

3840
// code mirror editor
3941
const editorRef = useRef<Editor>();
@@ -76,13 +78,19 @@ const CodeContent: React.FC<CodeContentProps> = ({
7678
endpointType: currentUser.endpointType,
7779
preferS3Adapter: domain.apiScope === BackendMode.S3,
7880
};
81+
const domainToGet = domain?.name === NON_OWNED_DOMAIN.name
82+
? undefined
83+
: domain;
7984
getContent(
8085
regionId,
8186
bucketName,
8287
filePath,
83-
domain.name === NON_OWNED_DOMAIN.name
84-
? undefined
85-
: domain,
88+
domainToGet,
89+
getStyleForSignature({
90+
domain: domainToGet,
91+
preferBackendMode,
92+
currentEndpointType: currentUser.endpointType,
93+
}),
8694
opt,
8795
)
8896
.then(contentBuffer => {

src/renderer/modules/qiniu-client/common.test.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@ import * as MockAuth from "@common/qiniu/_mock-helpers_/auth";
33

44
import { RegionService } from "kodo-s3-adapter-sdk/dist/region_service";
55

6-
jest.mock("kodo-s3-adapter-sdk/dist/region_service", () => ({
6+
jest.mock("kodo-s3-adapter-sdk/dist/region_service", () => {
7+
class MockedRegionService extends jest.fn() {
8+
static clearCache = jest.fn();
9+
clearCache = jest.fn();
10+
}
11+
return {
712
__esModule: true,
8-
RegionService: jest.fn().mockReturnValue({ clearCache: () => {} }),
9-
}));
13+
RegionService: MockedRegionService,
14+
}
15+
});
1016

1117
import { Kodo as KodoAdapter } from "kodo-s3-adapter-sdk/dist/kodo";
1218
import { S3 as S3Adapter } from "kodo-s3-adapter-sdk/dist/s3";

src/renderer/modules/qiniu-client/files.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ import {
2525
ObjectInfo,
2626
PartialObjectError,
2727
StorageClass,
28-
StorageObject
28+
StorageObject,
29+
UrlStyle,
2930
} from "kodo-s3-adapter-sdk/dist/adapter";
3031

3132
import Duration from "@common/const/duration";
@@ -443,6 +444,7 @@ describe("test qiniu-client/files.ts", () => {
443444
"bucket-kodo-browser-Kodo-getContent",
444445
qiniuPathConvertor.fromQiniuPath("qiniu-client/file-to-get"),
445446
mockDomain,
447+
undefined,
446448
mockOpt,
447449
);
448450
expect(QiniuClientCommon.getDefaultClient).toBeCalledTimes(1);
@@ -607,7 +609,7 @@ describe("test qiniu-client/files.ts", () => {
607609
mockDataKey,
608610
undefined,
609611
10,
610-
name === "S3" ? "path" : "bucketEndpoint",
612+
name === "S3" ? UrlStyle.Path : UrlStyle.BucketEndpoint,
611613
mockOpt,
612614
);
613615
expect(QiniuClientCommon.getDefaultClient).toBeCalledTimes(1);

src/renderer/modules/qiniu-client/files.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import * as qiniuPathConvertor from "qiniu-path/dist/src/convert";
22
import { Path as QiniuPath } from "qiniu-path/dist/src/path";
3-
import { Adapter, Domain, FrozenInfo, ObjectInfo, PartialObjectError, StorageClass, TransferObject } from 'kodo-s3-adapter-sdk/dist/adapter'
3+
import {
4+
Adapter,
5+
Domain,
6+
FrozenInfo,
7+
ObjectInfo,
8+
PartialObjectError,
9+
StorageClass,
10+
TransferObject,
11+
UrlStyle,
12+
} from 'kodo-s3-adapter-sdk/dist/adapter'
413

514
import {BackendMode} from "@common/qiniu";
615
import Duration from "@common/const/duration";
@@ -213,6 +222,7 @@ export async function getContent(
213222
bucket: string,
214223
key: QiniuPath | string,
215224
domain: Domain | undefined,
225+
style: UrlStyle | undefined,
216226
opt: GetAdapterOptionParam,
217227
):Promise<Buffer> {
218228
return await getDefaultClient(opt).enter("getContent", async client => {
@@ -223,6 +233,7 @@ export async function getContent(
223233
key: key.toString(),
224234
},
225235
domain,
236+
style,
226237
);
227238
return obj.data;
228239
}, {
@@ -333,14 +344,16 @@ export function getStyleForSignature({
333344
domain: Domain | undefined,
334345
preferBackendMode: BackendMode | undefined,
335346
currentEndpointType: EndpointType,
336-
}): "path" | "virtualHost" | "bucketEndpoint" {
347+
}): UrlStyle {
337348
if (domain?.apiScope === BackendMode.S3) {
338-
return "bucketEndpoint";
349+
return UrlStyle.BucketEndpoint;
339350
} else if (!domain || preferBackendMode === BackendMode.S3) {
340351
// some private cloud not support wildcard domain name resolving
341-
return currentEndpointType === EndpointType.Public ? "virtualHost" : "path";
352+
return currentEndpointType === EndpointType.Public
353+
? UrlStyle.VirtualHost
354+
: UrlStyle.Path;
342355
} else {
343-
return "bucketEndpoint";
356+
return UrlStyle.BucketEndpoint;
344357
}
345358
}
346359

@@ -350,7 +363,7 @@ export async function signatureUrl(
350363
key: QiniuPath | string,
351364
domain: Domain | undefined,
352365
expires: number, // seconds
353-
style: "path" | "virtualHost" | "bucketEndpoint",
366+
style: UrlStyle,
354367
opt: GetAdapterOptionParam,
355368
): Promise<URL> {
356369
const deadline = new Date();
@@ -909,7 +922,7 @@ export async function signatureUrls(
909922
items: FileItem.Item[],
910923
domain: Domain | undefined,
911924
expires: number,
912-
style: "path" | "virtualHost" | "bucketEndpoint",
925+
style: UrlStyle,
913926
progressFn: (progress: Progress) => void,
914927
onEachSuccess: (file: FileItem.File, url: URL) => void,
915928
onError: (err: any) => void,
@@ -969,4 +982,3 @@ export async function signatureUrls(
969982
return results;
970983
}
971984
}
972-

src/renderer/pages/browse/files/index.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import {useAuth} from "@renderer/modules/auth";
1414
import {KodoNavigator, useKodoNavigator} from "@renderer/modules/kodo-address";
1515
import {ContentViewStyle, appPreferences, useEndpointConfig} from "@renderer/modules/user-config-store";
1616

17-
import {BucketItem, FileItem, isAccelerateUploadingAvailable} from "@renderer/modules/qiniu-client";
18-
import {DomainAdapter, useLoadDomains, useLoadFiles} from "@renderer/modules/qiniu-client-hooks";
17+
import {BucketItem, FileItem, getStyleForSignature, isAccelerateUploadingAvailable} from "@renderer/modules/qiniu-client";
18+
import {DomainAdapter, NON_OWNED_DOMAIN, useLoadDomains, useLoadFiles} from "@renderer/modules/qiniu-client-hooks";
1919
import ipcDownloadManager from "@renderer/modules/electron-ipc-manages/ipc-download-manager";
2020
import * as AuditLog from "@renderer/modules/audit-log";
2121
import {useFileOperation} from "@renderer/modules/file-operation";
@@ -38,7 +38,10 @@ interface FilesProps {
3838
const Files: React.FC<FilesProps> = (props) => {
3939
const {currentLanguage, translate} = useI18n();
4040
const {currentUser, shareSession} = useAuth();
41-
const {bucketGrantedPermission} = useFileOperation();
41+
const {
42+
bucketPreferBackendMode: preferBackendMode,
43+
bucketGrantedPermission,
44+
} = useFileOperation();
4245

4346
const {
4447
state: appPreferencesState,
@@ -350,13 +353,21 @@ const Files: React.FC<FilesProps> = (props) => {
350353
to: destDirectoryPath,
351354
from: remoteObjects.map(i => i.key),
352355
});
356+
const domain = selectedDomain.name === NON_OWNED_DOMAIN.name
357+
? undefined
358+
: selectedDomain;
353359
ipcDownloadManager.addJobs({
354360
remoteObjects,
355361
destPath: destDirectoryPath,
356362
downloadOptions: {
357363
region: currentRegion.s3Id,
358364
bucket: currentBucket.name,
359-
domain: selectedDomain,
365+
domain: domain,
366+
urlStyle: getStyleForSignature({
367+
domain: domain,
368+
preferBackendMode,
369+
currentEndpointType: currentUser.endpointType,
370+
}),
360371
isOverwrite: appPreferencesData.overwriteDownloadEnabled,
361372
storageClasses: currentRegion.storageClasses,
362373
// userNatureLanguage needs mid-dash but i18n using lo_dash

0 commit comments

Comments
 (0)