Skip to content

Commit 0e619e4

Browse files
committed
fix harmony download
1 parent 791af98 commit 0e619e4

2 files changed

Lines changed: 96 additions & 25 deletions

File tree

harmony/pushy/src/main/ets/DownloadTask.ts

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ interface ZipFile {
1818
export class DownloadTask {
1919
private context: common.Context;
2020
private hash: string;
21-
private readonly DOWNLOAD_CHUNK_SIZE = 4096;
2221
private eventHub: EventHub;
2322

2423
constructor(context: common.Context) {
@@ -53,6 +52,35 @@ export class DownloadTask {
5352
private async downloadFile(params: DownloadTaskParams): Promise<void> {
5453
const httpRequest = http.createHttp();
5554
this.hash = params.hash;
55+
let writer: fileIo.File | null = null;
56+
let contentLength = 0;
57+
let received = 0;
58+
let writeError: Error | null = null;
59+
let writeQueue = Promise.resolve();
60+
61+
const closeWriter = async () => {
62+
if (writer) {
63+
await fileIo.close(writer);
64+
writer = null;
65+
}
66+
};
67+
68+
const dataEndPromise = new Promise<void>((resolve, reject) => {
69+
httpRequest.on('dataEnd', () => {
70+
writeQueue
71+
.then(async () => {
72+
if (writeError) {
73+
throw writeError;
74+
}
75+
await closeWriter();
76+
resolve();
77+
})
78+
.catch(async error => {
79+
await closeWriter();
80+
reject(error);
81+
});
82+
});
83+
});
5684

5785
try {
5886
let exists = fileIo.accessSync(params.targetFile);
@@ -69,40 +97,74 @@ export class DownloadTask {
6997
}
7098
}
7199

72-
const response = await httpRequest.request(params.url, {
100+
writer = await fileIo.open(
101+
params.targetFile,
102+
fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE,
103+
);
104+
105+
httpRequest.on('headersReceive', (header: Record<string, string>) => {
106+
if (!header) {
107+
return;
108+
}
109+
const lengthKey = Object.keys(header).find(
110+
key => key.toLowerCase() === 'content-length',
111+
);
112+
if (!lengthKey) {
113+
return;
114+
}
115+
const length = parseInt(header[lengthKey], 10);
116+
if (!Number.isNaN(length)) {
117+
contentLength = length;
118+
}
119+
});
120+
121+
httpRequest.on('dataReceive', (data: ArrayBuffer) => {
122+
if (writeError) {
123+
return;
124+
}
125+
received += data.byteLength;
126+
writeQueue = writeQueue.then(async () => {
127+
if (!writer || writeError) {
128+
return;
129+
}
130+
try {
131+
await fileIo.write(writer.fd, data);
132+
} catch (error) {
133+
writeError = error as Error;
134+
}
135+
});
136+
this.onProgressUpdate(received, contentLength);
137+
});
138+
139+
httpRequest.on(
140+
'dataReceiveProgress',
141+
(data: http.DataReceiveProgressInfo) => {
142+
if (data.totalSize > 0) {
143+
contentLength = data.totalSize;
144+
}
145+
if (data.receiveSize > received) {
146+
received = data.receiveSize;
147+
}
148+
this.onProgressUpdate(received, contentLength);
149+
},
150+
);
151+
152+
const responseCode = await httpRequest.requestInStream(params.url, {
73153
method: http.RequestMethod.GET,
74154
readTimeout: 60000,
75155
connectTimeout: 60000,
76156
header: {
77157
'Content-Type': 'application/octet-stream',
78158
},
79159
});
80-
if (response.responseCode > 299) {
81-
throw Error(`Server error: ${response.responseCode}`);
160+
if (responseCode > 299) {
161+
throw Error(`Server error: ${responseCode}`);
82162
}
83163

84-
const contentLength = parseInt(response.header['content-length'] || '0');
85-
const writer = await fileIo.open(
86-
params.targetFile,
87-
fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE,
88-
);
89-
let received = 0;
90-
const data = response.result as ArrayBuffer;
91-
const chunks = Math.ceil(data.byteLength / this.DOWNLOAD_CHUNK_SIZE);
92-
for (let i = 0; i < chunks; i++) {
93-
const start = i * this.DOWNLOAD_CHUNK_SIZE;
94-
const end = Math.min(start + this.DOWNLOAD_CHUNK_SIZE, data.byteLength);
95-
const chunk = data.slice(start, end);
96-
97-
await fileIo.write(writer.fd, chunk);
98-
received += chunk.byteLength;
99-
100-
this.onProgressUpdate(received, contentLength);
101-
}
102-
await fileIo.close(writer);
164+
await dataEndPromise;
103165
const stats = await fileIo.stat(params.targetFile);
104166
const fileSize = stats.size;
105-
if (fileSize !== contentLength) {
167+
if (contentLength > 0 && fileSize !== contentLength) {
106168
throw Error(
107169
`Download incomplete: expected ${contentLength} bytes but got ${stats.size} bytes`,
108170
);
@@ -111,6 +173,15 @@ export class DownloadTask {
111173
console.error('Download failed:', error);
112174
throw error;
113175
} finally {
176+
try {
177+
await closeWriter();
178+
} catch (closeError) {
179+
console.error('Failed to close file:', closeError);
180+
}
181+
httpRequest.off('headersReceive');
182+
httpRequest.off('dataReceive');
183+
httpRequest.off('dataReceiveProgress');
184+
httpRequest.off('dataEnd');
114185
httpRequest.destroy();
115186
}
116187
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-update",
3-
"version": "10.37.5",
3+
"version": "10.37.6",
44
"description": "react-native hot update",
55
"main": "src/index",
66
"scripts": {

0 commit comments

Comments
 (0)