react-native-blob-util 0.22.2 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -512,7 +512,7 @@ RCT_EXPORT_METHOD(ls:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve r
512
512
  RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) callback)
513
513
  {
514
514
 
515
- [ReactNativeBlobUtilFS getPathFromUri:target completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
515
+ [ReactNativeBlobUtilFS getPathFromUri:target completionHandler:^(NSString *path, PHAsset *asset) {
516
516
  __block NSMutableDictionary * result;
517
517
  if(path != nil)
518
518
  {
@@ -536,10 +536,29 @@ RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) call
536
536
  }
537
537
  else if(asset != nil)
538
538
  {
539
- __block NSNumber * size = [NSNumber numberWithLong:[asset size]];
540
- result = [asset metadata];
541
- [result setValue:size forKey:@"size"];
542
- callback(@[[NSNull null], result]);
539
+ // For PHAsset, get basic metadata
540
+ NSMutableDictionary *assetInfo = [NSMutableDictionary dictionary];
541
+ [assetInfo setValue:[NSNumber numberWithLong:asset.pixelWidth] forKey:@"width"];
542
+ [assetInfo setValue:[NSNumber numberWithLong:asset.pixelHeight] forKey:@"height"];
543
+ [assetInfo setValue:[NSNumber numberWithLong:asset.duration] forKey:@"duration"];
544
+ [assetInfo setValue:[NSDate date] forKey:@"lastModified"];
545
+ [assetInfo setValue:@"asset" forKey:@"type"];
546
+ [assetInfo setValue:@"PHAsset" forKey:@"filename"];
547
+
548
+ // Get actual file size by requesting image data
549
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
550
+ options.synchronous = YES;
551
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
552
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
553
+
554
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
555
+ if (imageData) {
556
+ [assetInfo setValue:[NSNumber numberWithLong:imageData.length] forKey:@"size"];
557
+ } else {
558
+ [assetInfo setValue:[NSNumber numberWithLong:0] forKey:@"size"];
559
+ }
560
+ callback(@[[NSNull null], assetInfo]);
561
+ }];
543
562
  }
544
563
  else
545
564
  {
@@ -597,7 +616,7 @@ RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTRespons
597
616
  callback:(RCTResponseSenderBlock)callback
598
617
  {
599
618
  // path = [ReactNativeBlobUtilFS getPathOfAsset:path];
600
- [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
619
+ [ReactNativeBlobUtilFS getPathFromUri:src completionHandler:^(NSString *path, PHAsset *asset) {
601
620
  NSError * error = nil;
602
621
  if(path == nil)
603
622
  {
@@ -709,7 +728,7 @@ RCT_EXPORT_METHOD(hash:(NSString *)path
709
728
  }
710
729
 
711
730
  #pragma mark - fs.readStream
712
- RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(int)bufferSize tick:(int)tick streamId:(NSString *)streamId)
731
+ RCT_EXPORT_METHOD(readStream:(NSString *)path encoding:(NSString *)encoding bufferSize:(double)bufferSize tick:(double)tick streamId:(NSString *)streamId)
713
732
  {
714
733
  if(bufferSize == 0) {
715
734
  if([[encoding lowercaseString] isEqualToString:@"base64"])
@@ -741,10 +760,12 @@ RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBl
741
760
  }
742
761
 
743
762
  #pragma mark - net.enableProgressReport
744
- RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count)
763
+ RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(double)interval count:(double)count)
745
764
  {
765
+ NSNumber *intervalNumber = [NSNumber numberWithDouble:interval];
766
+ NSNumber *countNumber = [NSNumber numberWithInteger:count];
746
767
 
747
- ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:interval count:count];
768
+ ReactNativeBlobUtilProgress * cfg = [[ReactNativeBlobUtilProgress alloc] initWithType:Download interval:intervalNumber count:countNumber];
748
769
  [[ReactNativeBlobUtilNetwork sharedInstance] enableProgressReport:taskId config:cfg];
749
770
  }
750
771
 
@@ -18,7 +18,7 @@
18
18
  #import "RCTBridgeModule.h"
19
19
  #endif
20
20
 
21
- #import <AssetsLibrary/AssetsLibrary.h>
21
+ #import <Photos/Photos.h>
22
22
 
23
23
  @interface ReactNativeBlobUtilFS : NSObject <NSStreamDelegate> {
24
24
  NSOutputStream * outStream;
@@ -57,7 +57,7 @@
57
57
  + (NSString *) getTempPath:(NSString*)taskId withExtension:(NSString *)ext;
58
58
  + (NSString *) getPathOfAsset:(NSString *)assetURI;
59
59
  + (NSString *) getPathForAppGroup:(NSString *)groupName;
60
- + (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete;
60
+ + (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, PHAsset *asset)) onComplete;
61
61
 
62
62
  // fs methods
63
63
  + (ReactNativeBlobUtilFS *) getFileStreams;
@@ -82,8 +82,8 @@
82
82
  resolver:(RCTPromiseResolveBlock)resolve
83
83
  rejecter:(RCTPromiseRejectBlock)reject;
84
84
  //+ (void) writeFileFromFile:(NSString *)src toFile:(NSString *)dest append:(BOOL)append;
85
- + (void) writeAssetToPath:(ALAssetRepresentation * )rep dest:(NSString *)dest;
86
- + (void) readStream:(NSString *)uri encoding:(NSString * )encoding bufferSize:(int)bufferSize tick:(int)tick streamId:(NSString *)streamId baseModule:(ReactNativeBlobUtil *)baseModule;
85
+ + (void) writeAssetToPath:(PHAsset * )asset dest:(NSString *)dest;
86
+ + (void) readStream:(NSString *)uri encoding:(NSString * )encoding bufferSize:(double)bufferSize tick:(double)tick streamId:(NSString *)streamId baseModule:(ReactNativeBlobUtil *)baseModule;
87
87
  + (void) df:(RCTResponseSenderBlock)callback;
88
88
 
89
89
  // constructor
@@ -11,7 +11,7 @@
11
11
  #import "ReactNativeBlobUtilFS.h"
12
12
  #import "ReactNativeBlobUtilConst.h"
13
13
  #import "ReactNativeBlobUtilFileTransformer.h"
14
- #import <AssetsLibrary/AssetsLibrary.h>
14
+ #import <Photos/Photos.h>
15
15
 
16
16
  #import <CommonCrypto/CommonDigest.h>
17
17
 
@@ -149,12 +149,12 @@ NSMutableDictionary *fileStreams = nil;
149
149
 
150
150
  + (void) readStream:(NSString *)uri
151
151
  encoding:(NSString * )encoding
152
- bufferSize:(int)bufferSize
153
- tick:(int)tick
152
+ bufferSize:(double)bufferSize
153
+ tick:(double)tick
154
154
  streamId:(NSString *)streamId
155
155
  baseModule:(ReactNativeBlobUtil*)baseModule
156
156
  {
157
- [[self class] getPathFromUri:uri completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
157
+ [[self class] getPathFromUri:uri completionHandler:^(NSString *path, PHAsset *asset) {
158
158
 
159
159
  __block int read = 0;
160
160
  __block int backoff = tick *1000;
@@ -188,17 +188,34 @@ NSMutableDictionary *fileStreams = nil;
188
188
  }
189
189
  else if (asset != nil)
190
190
  {
191
- int cursor = 0;
192
- NSError * err;
193
- while((read = [asset getBytes:buffer fromOffset:cursor length:bufferSize error:&err]) > 0)
194
- {
195
- cursor += read;
196
- [[self class] emitDataChunks:[NSData dataWithBytes:buffer length:read] encoding:encoding streamId:streamId baseModule:baseModule];
197
- if(tick > 0)
198
- {
199
- usleep(backoff);
200
- }
201
- }
191
+ // For PHAsset, we need to get the full image data first
192
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
193
+ options.synchronous = YES;
194
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
195
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
196
+
197
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
198
+ if (imageData) {
199
+ // Write to temporary file and then read it back in chunks
200
+ NSString *tempPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"temp_asset_%@.tmp", [[NSUUID UUID] UUIDString]]];
201
+ [imageData writeToFile:tempPath atomically:YES];
202
+
203
+ NSInputStream *stream = [[NSInputStream alloc] initWithFileAtPath:tempPath];
204
+ [stream open];
205
+ while((read = [stream read:buffer maxLength:bufferSize]) > 0)
206
+ {
207
+ [[self class] emitDataChunks:[NSData dataWithBytes:buffer length:read] encoding:encoding streamId:streamId baseModule:baseModule];
208
+ if(tick > 0)
209
+ {
210
+ usleep(backoff);
211
+ }
212
+ }
213
+ [stream close];
214
+
215
+ // Clean up temp file
216
+ [[NSFileManager defaultManager] removeItemAtPath:tempPath error:nil];
217
+ }
218
+ }];
202
219
  }
203
220
  else
204
221
  {
@@ -290,7 +307,7 @@ NSMutableDictionary *fileStreams = nil;
290
307
 
291
308
  + (NSNumber *) writeFileFromFile:(NSString *)src toFile:(NSString *)dest append:(BOOL)append callback:(void(^)(NSString * errMsg, NSNumber *size))callback
292
309
  {
293
- [[self class] getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
310
+ [[self class] getPathFromUri:src completionHandler:^(NSString *path, PHAsset *asset) {
294
311
  if(path != nil)
295
312
  {
296
313
  __block NSInputStream * is = [[NSInputStream alloc] initWithFileAtPath:path];
@@ -313,21 +330,24 @@ NSMutableDictionary *fileStreams = nil;
313
330
  }
314
331
  else if(asset != nil)
315
332
  {
316
-
317
- __block NSOutputStream * os = [[NSOutputStream alloc] initToFileAtPath:dest append:append];
318
- int read = 0;
319
- int cursor = 0;
320
- __block long written = 0;
321
- uint8_t buffer[10240];
322
- [os open];
323
- while((read = [asset getBytes:buffer fromOffset:cursor length:10240 error:nil]) > 0)
324
- {
325
- cursor += read;
326
- [os write:buffer maxLength:read];
327
- }
328
- __block NSNumber * size = [NSNumber numberWithLong:written];
329
- [os close];
330
- callback(nil, size);
333
+ // For PHAsset, get the full image data and write it
334
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
335
+ options.synchronous = YES;
336
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
337
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
338
+
339
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
340
+ if (imageData) {
341
+ NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:dest append:append];
342
+ [os open];
343
+ [imageData writeToFile:dest atomically:YES];
344
+ NSNumber *size = [NSNumber numberWithLong:imageData.length];
345
+ [os close];
346
+ callback(nil, size);
347
+ } else {
348
+ callback(@"Failed to get image data from asset", nil);
349
+ }
350
+ }];
331
351
  }
332
352
  else
333
353
  callback(@"failed to resolve path", nil);
@@ -496,23 +516,26 @@ NSMutableDictionary *fileStreams = nil;
496
516
  transformFile:(BOOL) transformFile
497
517
  onComplete:(void (^)(NSData * content, NSString * codeStr, NSString * errMsg))onComplete
498
518
  {
499
- [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
519
+ [[self class] getPathFromUri:path completionHandler:^(NSString *path, PHAsset *asset) {
500
520
  __block NSData * fileContent;
501
521
  NSError * err;
502
522
  __block Byte * buffer;
503
523
  if(asset != nil)
504
524
  {
505
- int size = asset.size;
506
- buffer = (Byte *)malloc(size);
507
- [asset getBytes:buffer fromOffset:0 length:asset.size error:&err];
508
- if(err != nil)
509
- {
510
- onComplete(nil, @"EUNSPECIFIED", [err description]);
511
- free(buffer);
512
- return;
513
- }
514
- fileContent = [NSData dataWithBytes:buffer length:size];
515
- free(buffer);
525
+ // For PHAsset, get the full image data
526
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
527
+ options.synchronous = YES;
528
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
529
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
530
+
531
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
532
+ if (imageData) {
533
+ onComplete(imageData, nil, nil);
534
+ } else {
535
+ onComplete(nil, @"EUNSPECIFIED", @"Failed to get image data from asset");
536
+ }
537
+ }];
538
+ return;
516
539
  }
517
540
  else
518
541
  {
@@ -795,7 +818,7 @@ typedef enum {
795
818
 
796
819
  + (void) exists:(NSString *) path callback:(RCTResponseSenderBlock)callback
797
820
  {
798
- [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset) {
821
+ [[self class] getPathFromUri:path completionHandler:^(NSString *path, PHAsset *asset) {
799
822
  if(path != nil)
800
823
  {
801
824
  BOOL isDir = NO;
@@ -886,7 +909,7 @@ typedef enum {
886
909
  resolver:(RCTPromiseResolveBlock)resolve
887
910
  rejecter:(RCTPromiseRejectBlock)reject
888
911
  {
889
- [[self class] getPathFromUri:path completionHandler:^(NSString *path, ALAssetRepresentation *asset)
912
+ [[self class] getPathFromUri:path completionHandler:^(NSString *path, PHAsset *asset)
890
913
  {
891
914
  if(path != nil)
892
915
  {
@@ -945,39 +968,34 @@ typedef enum {
945
968
  }
946
969
  else if (asset != nil)
947
970
  {
948
- long expected = [end longValue] - [start longValue];
949
- long read = 0;
950
- long chunkRead = 0;
951
- NSOutputStream * os = [[NSOutputStream alloc] initToFileAtPath:dest append:NO];
952
- [os open];
953
- long size = asset.size;
954
- long max = MIN(size, [end longValue]);
955
-
956
- while(read < expected) {
957
- uint8_t chunk[10240];
958
- uint8_t * pointerToChunk = &chunk[0];
959
- long chunkSize = 0;
960
- if([start longValue] + read + 10240 > max)
961
- {
962
- NSLog(@"read chunk %lu", max - read - [start longValue]);
963
- chunkSize = max - read - [start longValue];
964
- chunkRead = [asset getBytes:pointerToChunk fromOffset:[start longValue] + read length:chunkSize error:nil];
965
- }
966
- else
967
- {
968
- NSLog(@"read chunk %lu", 10240);
969
- chunkSize = 10240;
970
- chunkRead = [asset getBytes:pointerToChunk fromOffset:[start longValue] + read length:chunkSize error:nil];
971
+ // For PHAsset, get the full image data and then slice it
972
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
973
+ options.synchronous = YES;
974
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
975
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
976
+
977
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
978
+ if (imageData) {
979
+ long startPos = [start longValue];
980
+ long endPos = [end longValue];
981
+ long dataLength = imageData.length;
982
+
983
+ // Clamp the range to the actual data length
984
+ startPos = MAX(0, MIN(startPos, dataLength));
985
+ endPos = MAX(startPos, MIN(endPos, dataLength));
986
+
987
+ NSRange range = NSMakeRange(startPos, endPos - startPos);
988
+ NSData *sliceData = [imageData subdataWithRange:range];
989
+
990
+ if ([sliceData writeToFile:dest atomically:YES]) {
991
+ resolve(dest);
992
+ } else {
993
+ reject(@"EUNSPECIFIED", @"Failed to write slice to file", nil);
994
+ }
995
+ } else {
996
+ reject(@"EUNSPECIFIED", @"Failed to get image data from asset", nil);
971
997
  }
972
- if( chunkRead <= 0)
973
- break;
974
- long remain = expected - read;
975
-
976
- [os write:chunk maxLength:chunkSize];
977
- read += chunkRead;
978
- }
979
- [os close];
980
- resolve(dest);
998
+ }];
981
999
  }
982
1000
  else {
983
1001
  reject(@"EINVAL", [NSString stringWithFormat: @"Could not resolve URI %@", path ], nil);
@@ -1001,20 +1019,18 @@ typedef enum {
1001
1019
 
1002
1020
  # pragma mark - get absolute path of resource
1003
1021
 
1004
- + (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, ALAssetRepresentation *asset)) onComplete
1022
+ + (void) getPathFromUri:(NSString *)uri completionHandler:(void(^)(NSString * path, PHAsset *asset)) onComplete
1005
1023
  {
1006
1024
  if([uri hasPrefix:AL_PREFIX])
1007
1025
  {
1008
1026
  NSURL *asseturl = [NSURL URLWithString:uri];
1009
- __block ALAssetsLibrary* assetslibrary = [[ALAssetsLibrary alloc] init];
1010
- [assetslibrary assetForURL:asseturl
1011
- resultBlock:^(ALAsset *asset) {
1012
- __block ALAssetRepresentation * present = [asset defaultRepresentation];
1013
- onComplete(nil, present);
1014
- }
1015
- failureBlock:^(NSError *error) {
1016
- onComplete(nil, nil);
1017
- }];
1027
+ PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithALAssetURLs:@[asseturl] options:nil];
1028
+ if (assets.count > 0) {
1029
+ PHAsset *asset = assets.firstObject;
1030
+ onComplete(nil, asset);
1031
+ } else {
1032
+ onComplete(nil, nil);
1033
+ }
1018
1034
  }
1019
1035
  else
1020
1036
  {
@@ -1044,20 +1060,20 @@ typedef enum {
1044
1060
 
1045
1061
  }
1046
1062
 
1047
- + (void) writeAssetToPath:(ALAssetRepresentation * )rep dest:(NSString *)dest
1063
+ + (void) writeAssetToPath:(PHAsset * )asset dest:(NSString *)dest
1048
1064
  {
1049
- int read = 0;
1050
- int cursor = 0;
1051
- Byte * buffer = (Byte *)malloc(10240);
1052
- NSOutputStream * ostream = [[NSOutputStream alloc] initToFileAtPath:dest append:NO];
1053
- [ostream open];
1054
- while((read = [rep getBytes:buffer fromOffset:cursor length:10240 error:nil]) > 0)
1055
- {
1056
- cursor+=10240;
1057
- [ostream write:buffer maxLength:read];
1065
+ if (asset.mediaType == PHAssetMediaTypeImage) {
1066
+ PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
1067
+ options.synchronous = YES;
1068
+ options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
1069
+ options.resizeMode = PHImageRequestOptionsResizeModeNone;
1070
+
1071
+ [[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
1072
+ if (imageData) {
1073
+ [imageData writeToFile:dest atomically:YES];
1074
+ }
1075
+ }];
1058
1076
  }
1059
- [ostream close];
1060
- free(buffer);
1061
1077
  return;
1062
1078
  }
1063
1079
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-blob-util",
3
- "version": "0.22.2",
3
+ "version": "0.23.2",
4
4
  "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.",
5
5
  "main": "index",
6
6
  "scripts": {
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
17
17
  'ReactNativeBlobUtilPrivacyInfo' => ['ios/PrivacyInfo.xcprivacy'],
18
18
  }
19
19
  s.platforms = { :ios => "11.0" }
20
- s.framework = 'AssetsLibrary'
20
+ s.framework = 'Photos'
21
21
 
22
22
  if fabric_enabled
23
23
  # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.