Skip to content
This repository was archived by the owner on Jan 29, 2019. It is now read-only.

Commit 2118c95

Browse files
[WIP] feat: chunked uploads
1 parent 8b24710 commit 2118c95

File tree

4 files changed

+179
-137
lines changed

4 files changed

+179
-137
lines changed

src/classes/VTransmitFile.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@ declare class VTransmitFile {
3030
private _dataUrl;
3131
errorMessage: string;
3232
thumbnailLoaded: boolean;
33+
isChunked: boolean;
34+
chunkLength: number;
35+
chunkIndex: number;
3336
constructor(...data: object[]);
3437
set(...data: object[]): VTransmitFile;
3538
copyNativeFile(file: File): VTransmitFile;
3639
copyOwnAndInheritedProps(...data: object[]): VTransmitFile;
3740
handleProgress(e: ProgressEvent): void;
3841
startProgress(): VTransmitFile;
3942
endProgress(): VTransmitFile;
43+
chunkify(maxBytes: number): VTransmitFile[];
4044
nativeFile: File;
4145
dataUrl: string;
4246
static fromNativeFile(file: File, ...data: any[]): VTransmitFile;

src/classes/VTransmitFile.ts

+88-60
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
1-
import { assign, defineProperty, copyOwnAndInheritedProps, uniqueId, round, toKbps, toMbps } from "../core/utils"
1+
import { assign, defineProperty, copyOwnAndInheritedProps, uniqueId, round, toKbps, toMbps } from "../core/utils";
22

33
export interface IUploadStats {
4-
bytesSent: number
5-
progress: number
6-
total: number
7-
speed: ISpeedStats
8-
start: number
9-
end: number
10-
time: number
4+
bytesSent: number;
5+
progress: number;
6+
total: number;
7+
speed: ISpeedStats;
8+
start: number;
9+
end: number;
10+
time: number;
1111
}
1212

1313
export interface ISpeedStats {
14-
kbps: number
15-
mbps: number
14+
kbps: number;
15+
mbps: number;
1616
}
1717

1818
class VTransmitFile {
19-
private _nativeFile: File = null
20-
id: string = VTransmitFile.idFactory()
21-
accepted: boolean = undefined // Passed all validation.
22-
lastModified: number = undefined
23-
lastModifiedDate: Date = undefined
24-
name: string = undefined
25-
processing: boolean = undefined
26-
size: number = undefined
27-
status: string = undefined
28-
type: string = undefined
19+
private _nativeFile: File = null;
20+
id: string = VTransmitFile.idFactory();
21+
accepted: boolean = undefined; // Passed all validation.
22+
lastModified: number = undefined;
23+
lastModifiedDate: Date = undefined;
24+
name: string = undefined;
25+
processing: boolean = undefined;
26+
size: number = undefined;
27+
status: string = undefined;
28+
type: string = undefined;
2929
upload: IUploadStats = {
3030
bytesSent: 0,
3131
progress: 0,
@@ -37,82 +37,110 @@ class VTransmitFile {
3737
start: undefined,
3838
end: undefined,
3939
time: undefined,
40-
}
41-
webkitRelativePath: USVString = undefined
42-
width: number = undefined
43-
height: number = undefined
44-
xhr: XMLHttpRequest = undefined
45-
private _dataUrl: string
46-
errorMessage: string = undefined
47-
thumbnailLoaded: boolean = false
40+
};
41+
webkitRelativePath: USVString = undefined;
42+
width: number = undefined;
43+
height: number = undefined;
44+
xhr: XMLHttpRequest = undefined;
45+
private _dataUrl: string;
46+
errorMessage: string = undefined;
47+
thumbnailLoaded: boolean = false;
48+
isChunked: boolean = false;
49+
chunkLength: number = 1;
50+
chunkIndex: number = 0;
4851

4952
constructor(...data: object[]) {
50-
assign(this, ...data)
53+
assign(this, ...data);
5154
}
5255

5356
set(...data: object[]): VTransmitFile {
54-
assign(this, ...data)
55-
return this
57+
assign(this, ...data);
58+
return this;
5659
}
5760

5861
copyNativeFile(file: File): VTransmitFile {
5962
// save reference for upload
60-
this.nativeFile = file
63+
this.nativeFile = file;
6164
// Copy props to normal object for Vue reactivity.
6265
// Vue cannot define reactive properties on native file's readonly props.
63-
return this.set(copyOwnAndInheritedProps(file))
66+
return this.set(copyOwnAndInheritedProps(file));
6467
}
6568

6669
copyOwnAndInheritedProps(...data: object[]): VTransmitFile {
67-
return this.set(...data.map(copyOwnAndInheritedProps))
70+
return this.set(...data.map(copyOwnAndInheritedProps));
6871
}
6972

7073
handleProgress(e: ProgressEvent): void {
71-
this.startProgress()
72-
const total = e.total || this.upload.total
73-
this.upload.progress = Math.min(100, 100 * e.loaded / total)
74-
this.upload.bytesSent = e.loaded
75-
this.upload.total = total
76-
this.upload.time = (Date.now() - this.upload.start) / 1000
74+
this.startProgress();
75+
const total = e.total || this.upload.total;
76+
this.upload.progress = Math.min(100, (100 * e.loaded) / total);
77+
this.upload.bytesSent = e.loaded;
78+
this.upload.total = total;
79+
this.upload.time = (Date.now() - this.upload.start) / 1000;
7780
// Recalc the upload speed in bytes/sec
78-
this.upload.speed.kbps = round(toKbps(this.upload.bytesSent, this.upload.time))
79-
this.upload.speed.mbps = round(toMbps(this.upload.bytesSent, this.upload.time))
81+
this.upload.speed.kbps = round(toKbps(this.upload.bytesSent, this.upload.time));
82+
this.upload.speed.mbps = round(toMbps(this.upload.bytesSent, this.upload.time));
8083
if (this.upload.progress === 100) {
81-
this.endProgress()
84+
this.endProgress();
8285
}
8386
}
8487

8588
startProgress(): VTransmitFile {
8689
// Avoid starting twice
8790
if (typeof this.upload.start !== "number") {
88-
this.upload.start = Date.now()
91+
this.upload.start = Date.now();
8992
}
90-
return this
93+
return this;
9194
}
9295

9396
endProgress(): VTransmitFile {
9497
// Avoid ending twice
9598
if (typeof this.upload.end !== "number") {
96-
this.upload.end = Date.now()
97-
this.upload.time = (Date.now() - this.upload.start) / 1000
99+
this.upload.end = Date.now();
100+
this.upload.time = (Date.now() - this.upload.start) / 1000;
101+
}
102+
return this;
103+
}
104+
105+
chunkify(maxBytes: number) {
106+
if (this.size <= maxBytes) {
107+
return [VTransmitFile.fromNativeFile(this.nativeFile)];
98108
}
99-
return this
109+
110+
let chunks: VTransmitFile[] = [];
111+
let chunkLength = Math.ceil(this.size / maxBytes);
112+
113+
for (let chunkIndex = 0; chunkIndex < chunkLength; chunkIndex++) {
114+
let offset = chunkIndex * maxBytes;
115+
116+
chunks.push(
117+
VTransmitFile.fromNativeFile(
118+
new File([this.nativeFile.slice(offset, offset + maxBytes)], this.name, {
119+
type: this.type,
120+
lastModified: this.lastModified,
121+
}),
122+
{ chunkIndex, chunkLength, isChunked: true }
123+
)
124+
);
125+
}
126+
127+
return chunks;
100128
}
101129

102130
get nativeFile() {
103-
return this._nativeFile
131+
return this._nativeFile;
104132
}
105133

106134
set nativeFile(file: File) {
107135
if (!(file instanceof File)) {
108-
throw new TypeError(`[${VTransmitFile.name}] Expected an instance of File (native).`)
136+
throw new TypeError(`[${VTransmitFile.name}] Expected an instance of File (native).`);
109137
}
110-
this._nativeFile = file
111-
this.upload.total = file.size
138+
this._nativeFile = file;
139+
this.upload.total = file.size;
112140
}
113141

114142
get dataUrl() {
115-
return this.thumbnailLoaded ? this._dataUrl : (this._dataUrl || "")
143+
return this.thumbnailLoaded ? this._dataUrl : this._dataUrl || "";
116144
}
117145

118146
set dataUrl(value) {
@@ -121,19 +149,19 @@ class VTransmitFile {
121149
enumerable: false,
122150
configurable: true,
123151
writable: true,
124-
})
125-
this.thumbnailLoaded = true
152+
});
153+
this.thumbnailLoaded = true;
126154
}
127155

128156
static fromNativeFile(file: File, ...data) {
129-
const instance = new VTransmitFile(...data)
130-
instance.copyNativeFile(file)
131-
return instance
157+
const instance = new VTransmitFile(...data);
158+
instance.copyNativeFile(file);
159+
return instance;
132160
}
133161

134162
static idFactory() {
135-
return uniqueId("v-transmit-file-")
163+
return uniqueId("v-transmit-file-");
136164
}
137165
}
138166

139-
export default VTransmitFile
167+
export default VTransmitFile;

0 commit comments

Comments
 (0)