22
22
* SOFTWARE.
23
23
*/
24
24
25
- import { TurboModule , RNOHError } from '@rnoh/react-native-openharmony/ts' ;
26
- import fs , { ReadTextOptions , WriteOptions } from '@ohos.file.fs' ;
25
+ import { TurboModule , RNOHError , TurboModuleContext } from '@rnoh/react-native-openharmony/ts' ;
26
+ import { TM } from "@rnoh/react-native-openharmony/generated/ts"
27
+ import fs , { ListFileOptions , ReadOptions , ReadTextOptions , WriteOptions } from '@ohos.file.fs' ;
27
28
import hash from '@ohos.file.hash' ;
28
29
import { BusinessError } from '@ohos.base' ;
29
- import common from '@ohos.app.ability.common' ;
30
+ import resourceManager from '@ohos.resourceManager'
30
31
import util from '@ohos.util' ;
32
+ import loadRequest from '@ohos.request' ;
31
33
import buffer from '@ohos.buffer' ;
32
34
import HashMap from '@ohos.util.HashMap' ;
33
35
import Logger from './Logger' ;
36
+ import { Context } from '@ohos.abilityAccessCtrl' ;
37
+ import common from '@ohos.app.ability.common' ;
34
38
35
39
const TAG : string = "[RNOH] Fs"
36
40
@@ -43,11 +47,177 @@ interface StatResult {
43
47
type : number // Is the file just a file? Is the file a directory?
44
48
}
45
49
46
- export class FsTurboModule extends TurboModule {
50
+ type Headers = { [ name : string ] : string }
51
+ type Fields = { [ name : string ] : string }
52
+
53
+ type DownloadFileOptions = {
54
+ jobId : number
55
+ fromUrl : string // URL to download file from
56
+ toFile : string // Local filesystem path to save the file to
57
+ headers ?: Headers // An object of headers to be passed to the server
58
+ background ?: boolean // Continue the download in the background after the app terminates (iOS only)
59
+ progressInterval ?: number
60
+ progressDivider ?: number
61
+ readTimeout ?: number
62
+ hasBeginCallback ?: ( res : DownloadBeginCallbackResult ) => void
63
+ hasProgressCallback ?: ( res : DownloadProgressCallbackResult ) => void
64
+ hasResumableCallback ?: ( ) => void // only supported on iOS yet
65
+ connectionTimeout ?: number // only supported on Android yet
66
+ backgroundTimeout ?: number // Maximum time (in milliseconds) to download an entire resource (iOS only, useful for timing out background downloads)
67
+ }
68
+
69
+ type DownloadBeginCallbackResult = {
70
+ jobId : number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
71
+ statusCode : number // The HTTP status code
72
+ contentLength : number // The total size in bytes of the download resource
73
+ headers : Headers // The HTTP response headers from the server
74
+ }
75
+
76
+ type DownloadProgressCallbackResult = {
77
+ jobId : number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
78
+ contentLength : number // The total size in bytes of the download resource
79
+ bytesWritten : number // The number of bytes written to the file so far
80
+ }
81
+
82
+ type DownloadResult = {
83
+ jobId : number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
84
+ statusCode : number // The HTTP status code
85
+ bytesWritten : number // The number of bytes written to the file
86
+ }
87
+
88
+ type ReadDirItem = {
89
+ ctime ?: number ;
90
+ mtime ?: number ;
91
+ name : string ;
92
+ path : string ;
93
+ size : number ;
94
+ type : number ;
95
+ } ;
96
+
97
+ export class FsTurboModule extends TurboModule implements TM . ReactNativeFs . Spec {
98
+ private context : Context ; // ApplicationContext
99
+ private resourceManager : resourceManager . ResourceManager ;
100
+
101
+ constructor ( ctx : TurboModuleContext ) {
102
+ super ( ctx )
103
+ this . context = this . ctx . uiAbilityContext ;
104
+ this . resourceManager = this . context . resourceManager ;
105
+ }
106
+
107
+ existsAssets ( filepath : string ) : Promise < boolean > {
108
+ return new Promise ( ( resolve , reject ) => {
109
+ try {
110
+ this . resourceManager . getRawFileList ( filepath , ( error : BusinessError , value : Array < string > ) => {
111
+ if ( error != null ) {
112
+ resolve ( false ) ;
113
+ } else {
114
+ resolve ( true ) ;
115
+ }
116
+ } ) ;
117
+ } catch ( error ) {
118
+ resolve ( false ) ;
119
+ }
120
+ } ) ;
121
+ }
122
+
123
+ readDir ( dirpath : string ) : Promise < Object [ ] > {
124
+ return new Promise ( ( resolve , reject ) => {
125
+ let listFileOption : ListFileOptions = {
126
+ recursion : false ,
127
+ listNum : 0
128
+ } ;
129
+ fs . listFile ( dirpath , listFileOption , ( err : BusinessError , filenames : Array < string > ) => {
130
+ if ( err ) {
131
+ reject ( "list file failed with error message: " + err . message + ", error code: " + err . code ) ;
132
+ } else {
133
+ let readDirResult : ReadDirItem [ ] = [ ] ;
134
+ for ( let i = 0 ; i < filenames . length ; i ++ ) {
135
+ let filename = filenames [ i ] ;
136
+ let filePath = dirpath + filename ;
137
+ let file = fs . statSync ( filePath ) ;
138
+ readDirResult . push ( {
139
+ ctime : file . ctime ,
140
+ mtime : file . mtime ,
141
+ name : filename ,
142
+ path : filePath ,
143
+ size : file . size ,
144
+ type : file . isDirectory ( ) ? 1 : 0 ,
145
+ } ) ;
146
+ }
147
+ resolve ( readDirResult ) ;
148
+ }
149
+ } ) ;
150
+ } ) ;
151
+ }
152
+
153
+ downloadFile ( options : Object ) : Promise < DownloadResult > {
154
+ return new Promise ( ( resolve , reject ) => {
155
+ let downloadFileOptions : DownloadFileOptions = options as DownloadFileOptions ;
156
+ let downloadConfig : loadRequest . DownloadConfig = {
157
+ url : downloadFileOptions . fromUrl ,
158
+ header : downloadFileOptions . headers ,
159
+ enableMetered : true ,
160
+ enableRoaming : true ,
161
+ description : "" ,
162
+ filePath : downloadFileOptions . toFile ,
163
+ title : '' ,
164
+ background : true
165
+ } ;
166
+
167
+ loadRequest . downloadFile ( ( this . context as common . BaseContext ) , downloadConfig )
168
+ . then ( ( downloadTask : loadRequest . DownloadTask ) => {
169
+ if ( downloadTask ) {
170
+ let loadTask : loadRequest . DownloadTask | null = downloadTask ;
171
+
172
+ if ( downloadFileOptions . hasBeginCallback ) {
173
+ let downloadBeginCallbackResult : DownloadBeginCallbackResult = {
174
+ jobId : downloadFileOptions . jobId ,
175
+ statusCode : 0 ,
176
+ contentLength : 0 ,
177
+ headers : downloadFileOptions . headers
178
+ }
179
+ this . ctx . rnInstance . emitDeviceEvent ( 'DownloadBegin' , downloadBeginCallbackResult )
180
+ }
181
+ if ( downloadFileOptions . hasProgressCallback ) {
182
+ loadTask . on ( 'progress' , ( receivedSize , totalSize ) => {
183
+ if ( totalSize > 0 ) {
184
+ let downloadProgressCallbackResult : DownloadProgressCallbackResult = {
185
+ jobId : downloadFileOptions . jobId ,
186
+ contentLength : totalSize ,
187
+ bytesWritten : receivedSize
188
+ }
189
+ this . ctx . rnInstance . emitDeviceEvent ( 'DownloadProgress' , downloadProgressCallbackResult )
190
+ }
191
+ } ) ;
192
+ }
193
+
194
+ loadTask . on ( 'complete' , ( ) => {
195
+ let downloadResult : DownloadResult = {
196
+ jobId : downloadFileOptions . jobId ,
197
+ statusCode : 200 ,
198
+ bytesWritten : 0
199
+ }
200
+ resolve ( downloadResult ) ;
201
+ } )
202
+ loadTask . on ( 'pause' , ( ) => {
203
+ } )
204
+
205
+ loadTask . on ( 'remove' , ( ) => {
206
+ } )
207
+ loadTask . on ( 'fail' , ( err ) => {
208
+ reject ( JSON . stringify ( err ) ) ;
209
+ } )
210
+ } else {
211
+ reject ( "downloadTask dismiss" ) ;
212
+ }
213
+ } ) . catch ( ( err : BusinessError ) => {
214
+ reject ( JSON . stringify ( err ) ) ;
215
+ } )
216
+ } ) ;
217
+ }
47
218
48
- context = getContext ( this ) as common . ApplicationContext ; // ApplicationContext
49
219
// 常量
50
- getConstants ( ) : object {
220
+ getConstants ( ) : Object {
51
221
return {
52
222
// 沙箱路径
53
223
FileSandBoxPath : this . context . filesDir ,
@@ -63,14 +233,18 @@ export class FsTurboModule extends TurboModule {
63
233
// 读取文件内容
64
234
readFile ( path : string ) : Promise < string > {
65
235
return new Promise ( ( resolve , reject ) => {
66
- fs . readText ( path , ( err : BusinessError , content : string ) => {
236
+ let file = fs . openSync ( path , fs . OpenMode . READ_WRITE ) ;
237
+ let arrayBuffer = new ArrayBuffer ( 4096 ) ;
238
+ fs . read ( file . fd , arrayBuffer , ( err : BusinessError , readLen : number ) => {
67
239
if ( err ) {
68
- reject ( 'Failed to read the file' ) ;
240
+ reject ( "read failed with error message: " + err . message + ", error code: " + err . code ) ;
69
241
} else {
70
- let result = buffer . from ( content , 'utf8' ) . toString ( 'base64' ) ;
242
+ let result = buffer . from ( arrayBuffer , 0 , readLen ) . toString ( 'base64' ) ;
71
243
resolve ( result ) ;
72
244
}
245
+ fs . closeSync ( file ) ;
73
246
} ) ;
247
+
74
248
} )
75
249
} ;
76
250
@@ -145,8 +319,7 @@ export class FsTurboModule extends TurboModule {
145
319
// 资源文件内容读取
146
320
readFileAssets ( path : string ) : Promise < string > {
147
321
return new Promise ( ( resolve , reject ) => {
148
- this . context . resourceManager . getRawFileContent (
149
- path , ( err : BusinessError , value ) => {
322
+ this . resourceManager . getRawFileContent ( path , ( err : BusinessError , value : Uint8Array ) => {
150
323
if ( err ) {
151
324
reject ( err . message ) ;
152
325
} else {
0 commit comments