Skip to content

Commit 1080fae

Browse files
committed
writeFile() Android and iOS: improve errors; ReadStream: Add "ENOENT" (no such file) error event to Android version and add the thus far missing "code" parameter to iOS version
1 parent a9cb606 commit 1080fae

File tree

2 files changed

+118
-88
lines changed

2 files changed

+118
-88
lines changed

android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java

+31-25
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,27 @@ static void writeFile(String path, String encoding, String data, final boolean a
5555
int written;
5656
File f = new File(path);
5757
File dir = f.getParentFile();
58-
if(!dir.exists()) {
59-
boolean result = dir.mkdirs();
60-
if (!result) {
61-
promise.reject("EUNSPECIFIED", "Failed to create parent directory '" + path + "'");
62-
return;
63-
}
64-
}
58+
6559
if(!f.exists()) {
66-
boolean result = f.createNewFile();
67-
if (!result) {
68-
promise.reject("EUNSPECIFIED", "Failed to create file '" + path + "'");
60+
if(!dir.exists()) {
61+
if (!dir.mkdirs()) {
62+
promise.reject("EUNSPECIFIED", "Failed to create parent directory '" + path + "'");
63+
return;
64+
}
65+
}
66+
if(!f.createNewFile()) {
67+
promise.reject("ENOENT", "File '" + path + "' does not exist and could not be created");
6968
return;
7069
}
7170
}
71+
7272
FileOutputStream fout = new FileOutputStream(f, append);
7373
// write data from a file
7474
if(encoding.equalsIgnoreCase(RNFetchBlobConst.DATA_ENCODE_URI)) {
7575
String normalizedData = normalizePath(data);
7676
File src = new File(normalizedData);
7777
if (!src.exists()) {
78-
promise.reject("ENOENT", "No such file '" + normalizedData + "'");
78+
promise.reject("ENOENT", "No such file '" + path + "' " + "('" + normalizedData + "')");
7979
fout.close();
8080
return;
8181
}
@@ -114,20 +114,20 @@ static void writeFile(String path, ReadableArray data, final boolean append, fin
114114
try {
115115
File f = new File(path);
116116
File dir = f.getParentFile();
117-
if(!dir.exists()) {
118-
boolean result = dir.mkdirs();
119-
if (!result) {
120-
promise.reject("EUNSPECIFIED", "Failed to create parent directory '" + path + "'");
121-
return;
122-
}
123-
}
117+
124118
if(!f.exists()) {
125-
boolean result = f.createNewFile();
126-
if (!result) {
127-
promise.reject("ENOENT", "File '" + path + "' does not exist and could not be created, or it is a directory");
119+
if(!dir.exists()) {
120+
if (!dir.mkdirs()) {
121+
promise.reject("EUNSPECIFIED", "Failed to create parent directory '" + path + "'");
122+
return;
123+
}
124+
}
125+
if(!f.createNewFile()) {
126+
promise.reject("ENOENT", "File '" + path + "' does not exist and could not be created");
128127
return;
129128
}
130129
}
130+
131131
FileOutputStream os = new FileOutputStream(f, append);
132132
byte[] bytes = new byte[data.size()];
133133
for(int i=0;i<data.size();i++) {
@@ -138,7 +138,7 @@ static void writeFile(String path, ReadableArray data, final boolean append, fin
138138
promise.resolve(data.size());
139139
} catch (FileNotFoundException e) {
140140
// According to https://docs.oracle.com/javase/7/docs/api/java/io/FileOutputStream.html
141-
promise.reject("ENOENT", "File '" + path + "' does not exist and could not be created, or it is a directory");
141+
promise.reject("ENOENT", "File '" + path + "' does not exist and could not be created");
142142
} catch (Exception e) {
143143
promise.reject("EUNSPECIFIED", e.getLocalizedMessage());
144144
}
@@ -266,8 +266,8 @@ void readStream(String path, String encoding, int bufferSize, int tick, final St
266266
String resolved = normalizePath(path);
267267
if(resolved != null)
268268
path = resolved;
269-
try {
270269

270+
try {
271271
int chunkSize = encoding.equalsIgnoreCase("base64") ? 4095 : 4096;
272272
if(bufferSize > 0)
273273
chunkSize = bufferSize;
@@ -276,7 +276,6 @@ void readStream(String path, String encoding, int bufferSize, int tick, final St
276276

277277
if(resolved != null && path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) {
278278
fs = RNFetchBlob.RCTContext.getAssets().open(path.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, ""));
279-
280279
}
281280
// fix issue 287
282281
else if(resolved == null) {
@@ -336,7 +335,14 @@ else if(resolved == null) {
336335
emitStreamEvent(streamId, "end", "");
337336
fs.close();
338337
buffer = null;
339-
338+
} catch (FileNotFoundException err) {
339+
emitStreamEvent(
340+
streamId,
341+
"error",
342+
"ENOENT",
343+
"No such file '" + path + "'"
344+
);
345+
}
340346
} catch (Exception err) {
341347
emitStreamEvent(
342348
streamId,

ios/RNFetchBlobFS.m

+87-63
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ + (void) readStream:(NSString *)uri
166166
if([[NSFileManager defaultManager] fileExistsAtPath:path] == NO)
167167
{
168168
NSString * message = [NSString stringWithFormat:@"File does not exist at path %@", path];
169-
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"detail": message };
169+
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"code": @"ENOENT", @"detail": message };
170170
[event sendDeviceEventWithName:streamId body:payload];
171171
free(buffer);
172172
return ;
@@ -199,7 +199,7 @@ + (void) readStream:(NSString *)uri
199199
}
200200
else
201201
{
202-
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"detail": @"RNFetchBlob.readStream unable to resolve URI" };
202+
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"code": @"ENOENT", @"detail": @"Unable to resolve URI" };
203203
[event sendDeviceEventWithName:streamId body:payload];
204204
}
205205
// release buffer
@@ -209,7 +209,7 @@ + (void) readStream:(NSString *)uri
209209
}
210210
@catch (NSError * err)
211211
{
212-
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"detail": [NSString stringWithFormat:@"RNFetchBlob.readStream error %@", [err description]] };
212+
NSDictionary * payload = @{ @"event": FS_EVENT_ERROR, @"code": @"EUNSPECIFIED", @"detail": [err description] };
213213
[event sendDeviceEventWithName:streamId body:payload];
214214
}
215215
@finally
@@ -347,15 +347,21 @@ + (void) writeFile:(NSString *)path
347347
NSString * folder = [path stringByDeletingLastPathComponent];
348348
encoding = [encoding lowercaseString];
349349

350-
if(![fm fileExistsAtPath:folder]) {
350+
BOOL isDir = NO;
351+
BOOL exists = NO;
352+
exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory: &isDir];
353+
354+
if (isDir) {
355+
return reject(@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path], nil);
356+
}
357+
358+
if(!exists) {
351359
[fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
352360
if(err != nil) {
353-
reject(@"EUNSPECIFIED", [err description], nil);
354-
return;
361+
return reject(@"EUNSPECIFIED", @[[NSString stringWithFormat:@"Failed to create parent directory '%@', error: %@", path, [err description]]]], nil);
355362
}
356363
if(![fm createFileAtPath:path contents:nil attributes:nil]) {
357-
reject(@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created, or it is a directory", path], nil);
358-
return;
364+
return reject(@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created", path], nil);
359365
}
360366
}
361367

@@ -408,11 +414,19 @@ + (void) writeFileArray:(NSString *)path
408414
// check if the folder exists, if not exists, create folders recursively
409415
// after the folders created, write data into the file
410416
NSString * folder = [path stringByDeletingLastPathComponent];
411-
if(![fm fileExistsAtPath:folder]) {
417+
418+
BOOL isDir = NO;
419+
BOOL exists = NO;
420+
exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory: &isDir];
421+
422+
if (isDir) {
423+
return reject(@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path], nil);
424+
}
425+
426+
if(!exists) {
412427
[fm createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:NULL error:&err];
413428
if(err != nil) {
414-
reject(@"EUNSPECIFIED", [err description], nil);
415-
return;
429+
return reject(@"EUNSPECIFIED", @[[NSString stringWithFormat:@"Failed to create parent directory '%@', error: %@", path, [err description]]]], nil);
416430
}
417431
}
418432

@@ -423,8 +437,11 @@ + (void) writeFileArray:(NSString *)path
423437
bytes[i] = [[data objectAtIndex:i] charValue];
424438
}
425439
[fileContent appendBytes:bytes length:data.count];
426-
if(![fm fileExistsAtPath:path]) {
427-
[fm createFileAtPath:path contents:fileContent attributes:NULL];
440+
441+
if(!exists) {
442+
if(![fm createFileAtPath:path contents:fileContent attributes:NULL]) {
443+
return reject(@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created", path], nil);
444+
}
428445
}
429446
// if file exists, write file
430447
else {
@@ -513,73 +530,78 @@ + (void) readFile:(NSString *)path
513530

514531
# pragma mark - hash
515532

516-
RCT_EXPORT_METHOD(hash:(NSString *)filepath
533+
RCT_EXPORT_METHOD(hash:(NSString *)path
517534
algorithm:(NSString *)algorithm
518535
resolver:(RCTPromiseResolveBlock)resolve
519536
rejecter:(RCTPromiseRejectBlock)reject)
520537
{
521-
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filepath];
522-
523-
if (!fileExists) {
524-
return reject(@"ENOENT", [NSString stringWithFormat:@"No such file '%@'", filepath], nil);
525-
}
538+
BOOL isDir = NO;
539+
BOOL exists = NO;
540+
exists = [[NSFileManager defaultManager] fileExistsAtPath:path isDirectory: &isDir];
526541

527-
NSError *error = nil;
542+
if (isDir) {
543+
return reject(@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path], nil);
544+
}
545+
if (!fileExists) {
546+
return reject(@"ENOENT", [NSString stringWithFormat:@"No such file '%@'", path], nil);
547+
}
528548

529-
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:&error];
549+
NSError *error = nil;
530550

531-
if (error) {
532-
return [self reject:reject withError:error];
533-
}
551+
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&error];
534552

535-
if ([attributes objectForKey:NSFileType] == NSFileTypeDirectory) {
536-
return reject(@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", filepath], nil);
537-
}
553+
if (error) {
554+
return [self reject:reject withError:error];
555+
}
538556

539-
NSData *content = [[NSFileManager defaultManager] contentsAtPath:filepath];
557+
if ([attributes objectForKey:NSFileType] == NSFileTypeDirectory) {
558+
return reject(@"EISDIR", [NSString stringWithFormat:@"Expecting a file but '%@' is a directory", path], nil);
559+
}
540560

541-
NSArray *keys = [NSArray arrayWithObjects:@"md5", @"sha1", @"sha224", @"sha256", @"sha384", @"sha512", nil];
561+
NSData *content = [[NSFileManager defaultManager] contentsAtPath:path];
542562

543-
NSArray *digestLengths = [NSArray arrayWithObjects:
544-
@CC_MD5_DIGEST_LENGTH,
545-
@CC_SHA1_DIGEST_LENGTH,
546-
@CC_SHA224_DIGEST_LENGTH,
547-
@CC_SHA256_DIGEST_LENGTH,
548-
@CC_SHA384_DIGEST_LENGTH,
549-
@CC_SHA512_DIGEST_LENGTH,
550-
nil];
563+
NSArray *keys = [NSArray arrayWithObjects:@"md5", @"sha1", @"sha224", @"sha256", @"sha384", @"sha512", nil];
551564

552-
NSDictionary *keysToDigestLengths = [NSDictionary dictionaryWithObjects:digestLengths forKeys:keys];
565+
NSArray *digestLengths = [NSArray arrayWithObjects:
566+
@CC_MD5_DIGEST_LENGTH,
567+
@CC_SHA1_DIGEST_LENGTH,
568+
@CC_SHA224_DIGEST_LENGTH,
569+
@CC_SHA256_DIGEST_LENGTH,
570+
@CC_SHA384_DIGEST_LENGTH,
571+
@CC_SHA512_DIGEST_LENGTH,
572+
nil];
553573

554-
int digestLength = [[keysToDigestLengths objectForKey:algorithm] intValue];
574+
NSDictionary *keysToDigestLengths = [NSDictionary dictionaryWithObjects:digestLengths forKeys:keys];
555575

556-
if (!digestLength) {
557-
return reject(@"EINVAL", [NSString stringWithFormat:@"Invalid algorithm '%@', must be one of md5, sha1, sha224, sha256, sha384, sha512", algorithm], nil);
558-
}
576+
int digestLength = [[keysToDigestLengths objectForKey:algorithm] intValue];
559577

560-
unsigned char buffer[digestLength];
578+
if (!digestLength) {
579+
return reject(@"EINVAL", [NSString stringWithFormat:@"Invalid algorithm '%@', must be one of md5, sha1, sha224, sha256, sha384, sha512", algorithm], nil);
580+
}
561581

562-
if ([algorithm isEqualToString:@"md5"]) {
563-
CC_MD5(content.bytes, (CC_LONG)content.length, buffer);
564-
} else if ([algorithm isEqualToString:@"sha1"]) {
565-
CC_SHA1(content.bytes, (CC_LONG)content.length, buffer);
566-
} else if ([algorithm isEqualToString:@"sha224"]) {
567-
CC_SHA224(content.bytes, (CC_LONG)content.length, buffer);
568-
} else if ([algorithm isEqualToString:@"sha256"]) {
569-
CC_SHA256(content.bytes, (CC_LONG)content.length, buffer);
570-
} else if ([algorithm isEqualToString:@"sha384"]) {
571-
CC_SHA384(content.bytes, (CC_LONG)content.length, buffer);
572-
} else if ([algorithm isEqualToString:@"sha512"]) {
573-
CC_SHA512(content.bytes, (CC_LONG)content.length, buffer);
574-
} else {
575-
return reject(@"EINVAL", [NSString stringWithFormat:@"Invalid algorithm '%@', must be one of md5, sha1, sha224, sha256, sha384, sha512", algorithm], nil);
576-
}
582+
unsigned char buffer[digestLength];
583+
584+
if ([algorithm isEqualToString:@"md5"]) {
585+
CC_MD5(content.bytes, (CC_LONG)content.length, buffer);
586+
} else if ([algorithm isEqualToString:@"sha1"]) {
587+
CC_SHA1(content.bytes, (CC_LONG)content.length, buffer);
588+
} else if ([algorithm isEqualToString:@"sha224"]) {
589+
CC_SHA224(content.bytes, (CC_LONG)content.length, buffer);
590+
} else if ([algorithm isEqualToString:@"sha256"]) {
591+
CC_SHA256(content.bytes, (CC_LONG)content.length, buffer);
592+
} else if ([algorithm isEqualToString:@"sha384"]) {
593+
CC_SHA384(content.bytes, (CC_LONG)content.length, buffer);
594+
} else if ([algorithm isEqualToString:@"sha512"]) {
595+
CC_SHA512(content.bytes, (CC_LONG)content.length, buffer);
596+
} else {
597+
return reject(@"EINVAL", [NSString stringWithFormat:@"Invalid algorithm '%@', must be one of md5, sha1, sha224, sha256, sha384, sha512", algorithm], nil);
598+
}
577599

578-
NSMutableString *output = [NSMutableString stringWithCapacity:digestLength * 2];
579-
for(int i = 0; i < digestLength; i++)
580-
[output appendFormat:@"%02x",buffer[i]];
600+
NSMutableString *output = [NSMutableString stringWithCapacity:digestLength * 2];
601+
for(int i = 0; i < digestLength; i++)
602+
[output appendFormat:@"%02x",buffer[i]];
581603

582-
resolve(output);
604+
resolve(output);
583605
}
584606

585607
# pragma mark - mkdir
@@ -740,7 +762,9 @@ + (void)slice:(NSString *)path
740762
long max = MIN(size, [end longValue]);
741763

742764
if(![fm fileExistsAtPath:dest]) {
743-
[fm createFileAtPath:dest contents:@"" attributes:nil];
765+
if(![fm createFileAtPath:dest contents:@"" attributes:nil]) {
766+
return reject(@"ENOENT", [NSString stringWithFormat:@"File '%@' does not exist and could not be created", path], nil);
767+
}
744768
}
745769
[handle seekToFileOffset:[start longValue]];
746770
while(read < expected) {

0 commit comments

Comments
 (0)