Skip to content

Commit d4a0124

Browse files
committed
refactor(upload): streamline file upload process and rename methods for clarity
1 parent 7e71c75 commit d4a0124

6 files changed

Lines changed: 73 additions & 66 deletions

File tree

src/commands/upload-file.ts

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -83,37 +83,18 @@ export default class UploadFile extends Command {
8383
});
8484
progressBar.start(100, 0);
8585

86-
const minimumMultipartThreshold = 100 * 1024 * 1024;
87-
const useMultipart = stats.size > minimumMultipartThreshold;
88-
const partSize = 30 * 1024 * 1024;
89-
const parts = Math.ceil(stats.size / partSize);
90-
91-
let uploadOperation: Promise<
92-
[
93-
Promise<{
94-
fileId: string;
95-
hash: Buffer;
96-
}>,
97-
AbortController,
98-
]
99-
>;
100-
101-
if (useMultipart) {
102-
uploadOperation = networkFacade.uploadMultipartFromStream(user.bucket, user.mnemonic, stats.size, fileStream, {
103-
parts,
104-
progressCallback: (progress) => {
105-
progressBar.update(progress * 0.99);
106-
},
107-
});
108-
} else {
109-
uploadOperation = networkFacade.uploadFromStream(user.bucket, user.mnemonic, stats.size, fileStream, {
110-
progressCallback: (progress) => {
111-
progressBar.update(progress * 0.99);
112-
},
113-
});
114-
}
115-
116-
const [uploadPromise, abortable] = await uploadOperation;
86+
const progressCallback = (progress: number) => {
87+
progressBar.update(progress * 0.99);
88+
};
89+
90+
const [uploadPromise, abortable] = await UploadService.instance.uploadFileStream(
91+
fileStream,
92+
user.bucket,
93+
user.mnemonic,
94+
stats.size,
95+
networkFacade,
96+
progressCallback,
97+
);
11798

11899
process.on('SIGINT', () => {
119100
abortable.abort('SIGINT received');

src/services/network/network-facade.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export class NetworkFacade {
165165
};
166166

167167
const uploadFile: UploadFileFunction = async (url) => {
168-
await this.uploadService.uploadFile(url, encryptionTransform, {
168+
await this.uploadService.uploadFileToNetwork(url, encryptionTransform, {
169169
abortController: abortable,
170170
progressCallback: onProgress,
171171
});
@@ -244,7 +244,7 @@ export class NetworkFacade {
244244
const limitConcurrency = 6;
245245

246246
const uploadPart = async (upload: UploadTask) => {
247-
const { etag } = await this.uploadService.uploadFile(upload.urlToUpload, upload.contentToUpload, {
247+
const { etag } = await this.uploadService.uploadFileToNetwork(upload.urlToUpload, upload.contentToUpload, {
248248
abortController: abortable,
249249
progressCallback: (loadedBytes: number) => {
250250
onProgress(upload.index, loadedBytes);

src/services/network/upload.service.ts

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { Readable } from 'node:stream';
22
import axios from 'axios';
33
import { UploadOptions } from '../../types/network.types';
4+
import { NetworkFacade } from './network-facade.service';
45

56
export class UploadService {
67
public static readonly instance: UploadService = new UploadService();
78

8-
async uploadFile(url: string, from: Readable | Buffer, options: UploadOptions): Promise<{ etag: string }> {
9+
public uploadFileToNetwork = async (
10+
url: string,
11+
from: Readable | Buffer,
12+
options: UploadOptions,
13+
): Promise<{ etag: string }> => {
914
const response = await axios.put(url, from, {
1015
signal: options.abortController?.signal,
1116
onUploadProgress: (progressEvent) => {
@@ -20,5 +25,44 @@ export class UploadService {
2025
throw new Error('Missing Etag in response when uploading file');
2126
}
2227
return { etag };
23-
}
28+
};
29+
30+
public uploadFileStream = async (
31+
fileStream: Readable,
32+
userBucket: string,
33+
userMnemonic: string,
34+
fileSize: number,
35+
networkFacade: NetworkFacade,
36+
progressCallback?: (progress: number) => void,
37+
) => {
38+
const minimumMultipartThreshold = 100 * 1024 * 1024;
39+
const useMultipart = fileSize > minimumMultipartThreshold;
40+
const partSize = 30 * 1024 * 1024;
41+
const parts = Math.ceil(fileSize / partSize);
42+
43+
let uploadOperation: Promise<
44+
[
45+
Promise<{
46+
fileId: string;
47+
hash: Buffer;
48+
}>,
49+
AbortController,
50+
]
51+
>;
52+
53+
if (useMultipart) {
54+
uploadOperation = networkFacade.uploadMultipartFromStream(userBucket, userMnemonic, fileSize, fileStream, {
55+
parts,
56+
progressCallback,
57+
});
58+
} else {
59+
uploadOperation = networkFacade.uploadFromStream(userBucket, userMnemonic, fileSize, fileStream, {
60+
progressCallback,
61+
});
62+
}
63+
64+
const uploadFileOperation = await uploadOperation;
65+
66+
return uploadFileOperation;
67+
};
2468
}

src/types/network.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface NetworkCredentials {
66
export type DownloadProgressCallback = (downloadedBytes: number) => void;
77
export type UploadProgressCallback = (uploadedBytes: number) => void;
88
export interface NetworkOperationBaseOptions {
9-
progressCallback: UploadProgressCallback;
9+
progressCallback?: UploadProgressCallback;
1010
abortController?: AbortController;
1111
}
1212

src/webdav/handlers/PUT.handler.ts

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { DriveFolderService } from '../../services/drive/drive-folder.service';
1212
import { TrashService } from '../../services/drive/trash.service';
1313
import { EncryptionVersion } from '@internxt/sdk/dist/drive/storage/types';
1414
import { CLIUtils } from '../../utils/cli.utils';
15+
import { UploadService } from '../../services/network/upload.service';
1516

1617
export class PUTRequestHandler implements WebDavMethodHandler {
1718
constructor(
@@ -71,37 +72,18 @@ export class PUTRequestHandler implements WebDavMethodHandler {
7172

7273
const timer = CLIUtils.timer();
7374

74-
const minimumMultipartThreshold = 100 * 1024 * 1024;
75-
const useMultipart = contentLength > minimumMultipartThreshold;
76-
const partSize = 30 * 1024 * 1024;
77-
const parts = Math.ceil(contentLength / partSize);
78-
79-
let uploadOperation: Promise<
80-
[
81-
Promise<{
82-
fileId: string;
83-
hash: Buffer;
84-
}>,
85-
AbortController,
86-
]
87-
>;
88-
8975
const progressCallback = (progress: number) => {
9076
webdavLogger.info(`[PUT] Upload progress for file ${resource.name}: ${progress}%`);
9177
};
9278

93-
if (useMultipart) {
94-
uploadOperation = networkFacade.uploadMultipartFromStream(user.bucket, user.mnemonic, contentLength, req, {
95-
parts,
96-
progressCallback,
97-
});
98-
} else {
99-
uploadOperation = networkFacade.uploadFromStream(user.bucket, user.mnemonic, contentLength, req, {
100-
progressCallback,
101-
});
102-
}
103-
104-
const [uploadPromise, abortable] = await uploadOperation;
79+
const [uploadPromise, abortable] = await UploadService.instance.uploadFileStream(
80+
req,
81+
user.bucket,
82+
user.mnemonic,
83+
contentLength,
84+
networkFacade,
85+
progressCallback,
86+
);
10587

10688
let uploaded = false;
10789
res.on('close', () => {

test/services/network/upload.service.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ describe('Upload Service', () => {
2828
nock('https://example.com').put('/upload').reply(200, '', {});
2929

3030
try {
31-
await sut.uploadFile(url, data, options);
31+
await sut.uploadFileToNetwork(url, data, options);
3232
} catch (error) {
3333
expect((error as Error).message).to.contain('Missing Etag');
3434
}
@@ -52,7 +52,7 @@ describe('Upload Service', () => {
5252
etag: 'test-etag',
5353
});
5454

55-
const result = await sut.uploadFile(url, data, options);
55+
const result = await sut.uploadFileToNetwork(url, data, options);
5656
expect(result.etag).to.be.equal('test-etag');
5757
});
5858

@@ -74,7 +74,7 @@ describe('Upload Service', () => {
7474
etag: 'test-etag',
7575
});
7676

77-
await sut.uploadFile(url, data, options);
77+
await sut.uploadFileToNetwork(url, data, options);
7878
expect(options.progressCallback).toHaveBeenCalledWith(file.length);
7979
});
8080

0 commit comments

Comments
 (0)