Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1642,4 +1642,4 @@ EXAMPLES

# Current Limitations

- We currently have a 20GB size upload limitation per file for both, CLI and WebDAV
- We currently have a 40GB size upload limitation per file for both, CLI and WebDAV
2 changes: 1 addition & 1 deletion WEBDAV.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ No plain data is being sent or is being pulled from the Internxt servers, you ca

![image](https://raw.githubusercontent.com/internxt/cli/main/public/webdav-how-it-works.png)

_We currently have a 20GB size upload limitation per file for both, CLI and WebDAV_
_We currently have a 40GB size upload limitation per file for both, CLI and WebDAV_

## Officially supported WebDav clients

Expand Down
24 changes: 12 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"author": "Internxt <hello@internxt.com>",
"version": "1.6.3",
"version": "1.6.4",
"description": "Internxt CLI to manage your encrypted storage",
"scripts": {
"build": "yarn clean && tsc",
Expand Down Expand Up @@ -37,22 +37,22 @@
],
"dependencies": {
"@dashlane/pqc-kem-kyber512-node": "1.0.0",
"@inquirer/prompts": "8.3.0",
"@internxt/inxt-js": "2.3.1",
"@inquirer/prompts": "8.3.2",
"@internxt/inxt-js": "3.0.1",
"@internxt/lib": "1.4.1",
"@internxt/sdk": "1.15.3",
"@oclif/core": "4.9.0",
"@oclif/plugin-autocomplete": "3.2.40",
"@oclif/plugin-autocomplete": "3.2.41",
"axios": "1.13.6",
"better-sqlite3": "12.6.2",
"better-sqlite3": "12.8.0",
"bip39": "3.1.0",
"body-parser": "2.2.2",
"cli-progress": "3.12.0",
"dayjs": "1.11.19",
"dayjs": "1.11.20",
"dotenv": "17.3.1",
"express": "5.2.1",
"express-async-handler": "1.2.0",
"fast-xml-parser": "5.4.2",
"fast-xml-parser": "5.5.6",
"hash-wasm": "4.12.0",
"mime-types": "3.0.2",
"open": "11.0.0",
Expand All @@ -74,19 +74,19 @@
"@types/mime-types": "3.0.1",
"@types/node": "25.5.0",
"@types/range-parser": "1.2.7",
"@vitest/coverage-istanbul": "4.0.18",
"@vitest/spy": "4.0.18",
"@vitest/coverage-istanbul": "4.1.0",
"@vitest/spy": "4.1.0",
"eslint": "9.39.4",
"husky": "9.1.7",
"lint-staged": "16.3.3",
"lint-staged": "16.4.0",
"nodemon": "3.1.14",
"oclif": "4.22.85",
"oclif": "4.22.92",
"prettier": "3.8.1",
"rimraf": "6.1.3",
"sql.js": "1.14.1",
"ts-node": "10.9.2",
"typescript": "5.9.3",
"vitest": "4.0.18",
"vitest": "4.1.0",
"vitest-mock-express": "2.2.0"
},
"optionalDependencies": {
Expand Down
30 changes: 13 additions & 17 deletions src/commands/upload-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,19 @@ export default class UploadFile extends Command {
progressBar?.update(progress * 100 * 0.99);
};

fileId = await new Promise((resolve: (fileId: string) => void, reject) => {
const state = networkFacade.uploadFile(
fileStream,
fileSize,
bucket,
(err: Error | null, res: string | null) => {
if (err) {
return reject(err);
}
resolve(res as string);
},
progressCallback,
);
process.on('SIGINT', () => {
state.stop();
process.exit(1);
});
const abortable = new AbortController();

fileId = await networkFacade.uploadFile({
from: fileStream,
size: fileSize,
bucketId: bucket,
progressCallback,
abortSignal: abortable.signal,
});

process.on('SIGINT', () => {
abortable.abort();
process.exit(1);
});
}
timings.networkUpload = networkUploadTimer.stop();
Expand Down
59 changes: 30 additions & 29 deletions src/services/network/network-facade.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { CryptoService } from '../crypto.service';
import { DownloadService } from './download.service';
import { ValidationService } from '../validation.service';
import { RangeOptions } from '../../utils/network.utils';
import { ActionState } from '@internxt/inxt-js/build/api';
import { EncryptProgressCallback } from '@internxt/inxt-js/build/lib/core';

const TWENTY_GIGABYTES = 20 * 1024 * 1024 * 1024;
const FORTY_GIGABYTES = 40 * 1024 * 1024 * 1024;

export class NetworkFacade {
private readonly cryptoLib: Network.Crypto;
Expand Down Expand Up @@ -118,35 +118,36 @@ export class NetworkFacade {
* @param bucketId The bucket where the file will be uploaded
* @param size The total size of the stream content
* @param from The source ReadStream to upload from
* @returns A promise to execute the upload and an abort controller to cancel the upload
* @param progressCallback A callback to update the upload progress
* @param abortSignal A signal to abort the upload
* @param encryptProgressCallback A callback to update the encryption progress
* @returns A promise to execute the upload
*/
public uploadFile = (
from: Readable,
size: number,
bucketId: string,
finishedCallback: (err: Error | null, res: string | null) => void,
progressCallback: (progress: number) => void,
): ActionState => {
if (size > TWENTY_GIGABYTES) {
throw new Error('File is too big (more than 20 GB)');
public uploadFile = ({
from,
size,
bucketId,
progressCallback,
abortSignal,
encryptProgressCallback,
}: {
from: Readable;
size: number;
bucketId: string;
progressCallback: (progress: number) => void;
abortSignal?: AbortSignal;
encryptProgressCallback?: EncryptProgressCallback;
}): Promise<string> => {
if (size > FORTY_GIGABYTES) {
throw new Error('File is too big (more than 40 GB)');
}
const minimumMultipartThreshold = 100 * 1024 * 1024;
const useMultipart = size > minimumMultipartThreshold;

if (useMultipart) {
return this.environment.uploadMultipartFile(bucketId, {
source: from,
fileSize: size,
finishedCallback,
progressCallback,
});
} else {
return this.environment.upload(bucketId, {
source: from,
fileSize: size,
finishedCallback,
progressCallback,
});
}
return this.environment.upload(bucketId, {
source: from,
fileSize: size,
progressCallback,
abortSignal,
encryptProgressCallback,
});
};
}
18 changes: 5 additions & 13 deletions src/services/network/upload/upload-file.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,11 @@ export class UploadFileService {
const uploadTimer = CLIUtils.timer();
thumbnailStream = bufferStream;

fileId = await new Promise<string>((resolve, reject) => {
network.uploadFile(
fileStream,
fileSize,
bucket,
(err: Error | null, res: string | null) => {
if (err) {
return reject(err);
}
resolve(res as string);
},
() => {},
);
fileId = await network.uploadFile({
from: fileStream,
size: fileSize,
bucketId: bucket,
progressCallback: () => {},
});
timings.networkUpload = uploadTimer.stop();
}
Expand Down
18 changes: 5 additions & 13 deletions src/services/thumbnail.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,11 @@ export class ThumbnailService {
if (thumbnailBuffer) {
const size = thumbnailBuffer.length;

const fileId = await new Promise((resolve: (fileId: string) => void, reject) => {
networkFacade.uploadFile(
Readable.from(thumbnailBuffer),
size,
userBucket,
(err: Error | null, res: string | null) => {
if (err) {
return reject(err);
}
resolve(res as string);
},
() => {},
);
const fileId = await networkFacade.uploadFile({
from: Readable.from(thumbnailBuffer),
size: size,
bucketId: userBucket,
progressCallback: () => {},
});

const createdThumbnailFile = await DriveFileService.instance.createThumbnail({
Expand Down
Loading
Loading