rn-file-toolkit 1.0.1 → 1.0.3
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.
- package/README.md +152 -432
- package/android/src/main/java/com/filetoolkit/FileToolkitModule.kt +142 -12
- package/ios/FileToolkit.mm +219 -110
- package/lib/commonjs/index.js +147 -562
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +147 -562
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +27 -443
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +27 -443
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/package.json +10 -3
- package/src/index.tsx +177 -783
package/ios/FileToolkit.mm
CHANGED
|
@@ -137,7 +137,7 @@ RCT_EXPORT_MODULE()
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
BOOL isBackground = [options[@"background"] boolValue];
|
|
140
|
-
NSString *downloadId = [self generateDownloadId];
|
|
140
|
+
NSString *downloadId = options[@"downloadId"] ?: [self generateDownloadId];
|
|
141
141
|
NSURL *url = [NSURL URLWithString:urlString];
|
|
142
142
|
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
|
|
143
143
|
|
|
@@ -376,6 +376,14 @@ RCT_EXPORT_MODULE()
|
|
|
376
376
|
return;
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
+
// Safety check: reject files > 50MB to prevent crashing the RN bridge
|
|
380
|
+
NSDictionary *attrs = [fm attributesOfItemAtPath:filePath error:nil];
|
|
381
|
+
unsigned long long fileSize = [attrs fileSize];
|
|
382
|
+
if (fileSize > 50 * 1024 * 1024) {
|
|
383
|
+
resolve(@{@"success": @NO, @"error": @"File exceeds 50MB limit for readFile. Use streaming or base64 encoding for large files."});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
379
387
|
NSError *readError = nil;
|
|
380
388
|
NSData *raw = [NSData dataWithContentsOfFile:filePath options:0 error:&readError];
|
|
381
389
|
if (!raw || readError) {
|
|
@@ -651,9 +659,14 @@ didCompleteWithError:(NSError *)error {
|
|
|
651
659
|
if (uploadId) {
|
|
652
660
|
NSDictionary *funcs = self.uploadPromises[uploadId];
|
|
653
661
|
RCTPromiseResolveBlock uploadResolve = funcs[@"resolve"];
|
|
662
|
+
NSString *tempFile = funcs[@"tempFile"];
|
|
663
|
+
|
|
664
|
+
if (tempFile) {
|
|
665
|
+
[[NSFileManager defaultManager] removeItemAtPath:tempFile error:nil];
|
|
666
|
+
}
|
|
654
667
|
|
|
655
668
|
if (error) {
|
|
656
|
-
if (uploadResolve) uploadResolve(@{@"success": @NO, @"error": error.localizedDescription});
|
|
669
|
+
if (uploadResolve) uploadResolve(@{@"success": @NO, @"error": error.localizedDescription, @"uploadId": uploadId});
|
|
657
670
|
} else {
|
|
658
671
|
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
|
|
659
672
|
NSData *responseData = self.uploadResponseData[uploadId] ?: [NSData data];
|
|
@@ -662,7 +675,8 @@ didCompleteWithError:(NSError *)error {
|
|
|
662
675
|
if (uploadResolve) uploadResolve(@{
|
|
663
676
|
@"success": @(httpResponse.statusCode >= 200 && httpResponse.statusCode < 300),
|
|
664
677
|
@"status": @(httpResponse.statusCode),
|
|
665
|
-
@"data": respString
|
|
678
|
+
@"data": respString,
|
|
679
|
+
@"uploadId": uploadId
|
|
666
680
|
});
|
|
667
681
|
}
|
|
668
682
|
|
|
@@ -778,7 +792,7 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
|
|
|
778
792
|
if (totalBytesExpectedToSend > 0) {
|
|
779
793
|
int progress = (int)((totalBytesSent * 100) / totalBytesExpectedToSend);
|
|
780
794
|
[self sendEventWithName:@"onUploadProgress"
|
|
781
|
-
body:@{@"url": url, @"progress": @(progress)}];
|
|
795
|
+
body:@{@"url": url, @"uploadId": uploadId, @"progress": @(progress)}];
|
|
782
796
|
}
|
|
783
797
|
}
|
|
784
798
|
|
|
@@ -822,6 +836,7 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
|
|
|
822
836
|
return;
|
|
823
837
|
}
|
|
824
838
|
|
|
839
|
+
NSString *uploadId = options[@"uploadId"] ?: [self generateDownloadId];
|
|
825
840
|
NSString *fieldName = options[@"fieldName"] ?: @"file";
|
|
826
841
|
NSDictionary *headers = options[@"headers"];
|
|
827
842
|
NSDictionary *params = options[@"parameters"];
|
|
@@ -837,28 +852,63 @@ totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
|
|
|
837
852
|
}
|
|
838
853
|
}
|
|
839
854
|
|
|
840
|
-
|
|
855
|
+
// Create a temporary file to avoid OutOfMemory crash for large uploads
|
|
856
|
+
NSString *tempFileName = [NSString stringWithFormat:@"upload_%@.tmp", [[NSUUID UUID] UUIDString]];
|
|
857
|
+
NSString *tempFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:tempFileName];
|
|
858
|
+
|
|
859
|
+
[[NSFileManager defaultManager] createFileAtPath:tempFilePath contents:nil attributes:nil];
|
|
860
|
+
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:tempFilePath];
|
|
861
|
+
if (!fileHandle) {
|
|
862
|
+
resolve(@{@"success": @NO, @"error": @"Failed to create temp file for upload"});
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
NSMutableData *preamble = [NSMutableData data];
|
|
841
867
|
[params enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
|
|
842
|
-
[
|
|
843
|
-
[
|
|
844
|
-
[
|
|
868
|
+
[preamble appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
869
|
+
[preamble appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
870
|
+
[preamble appendData:[[NSString stringWithFormat:@"%@\r\n", value] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
845
871
|
}];
|
|
846
872
|
|
|
847
873
|
NSString *fileName = [filePath lastPathComponent];
|
|
848
|
-
[
|
|
849
|
-
[
|
|
850
|
-
[
|
|
851
|
-
|
|
852
|
-
[
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
874
|
+
[preamble appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
875
|
+
[preamble appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, fileName] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
876
|
+
[preamble appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
|
877
|
+
|
|
878
|
+
[fileHandle writeData:preamble];
|
|
879
|
+
|
|
880
|
+
// Stream the actual file content to the temp file
|
|
881
|
+
NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:filePath];
|
|
882
|
+
[inputStream open];
|
|
883
|
+
uint8_t buffer[32768]; // 32KB chunks
|
|
884
|
+
while ([inputStream hasBytesAvailable]) {
|
|
885
|
+
NSInteger bytesRead = [inputStream read:buffer maxLength:sizeof(buffer)];
|
|
886
|
+
if (bytesRead > 0) {
|
|
887
|
+
[fileHandle writeData:[NSData dataWithBytes:buffer length:bytesRead]];
|
|
888
|
+
} else if (bytesRead < 0) {
|
|
889
|
+
break;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
[inputStream close];
|
|
893
|
+
|
|
894
|
+
NSMutableData *postamble = [NSMutableData data];
|
|
895
|
+
[postamble appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
|
896
|
+
[postamble appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
|
897
|
+
[fileHandle writeData:postamble];
|
|
898
|
+
[fileHandle closeFile];
|
|
899
|
+
|
|
900
|
+
NSURL *tempFileURL = [NSURL fileURLWithPath:tempFilePath];
|
|
901
|
+
|
|
902
|
+
// Use delegate-based session for upload progress support with fromFile: instead of fromData:
|
|
903
|
+
NSURLSessionUploadTask *task = [self.fgSession uploadTaskWithRequest:request fromFile:tempFileURL];
|
|
858
904
|
NSString *taskKey = [NSString stringWithFormat:@"%lu", (unsigned long)task.taskIdentifier];
|
|
859
905
|
|
|
860
906
|
self.uploadTaskIdMap[taskKey] = uploadId;
|
|
861
|
-
self.uploadPromises[uploadId] = @{
|
|
907
|
+
self.uploadPromises[uploadId] = @{
|
|
908
|
+
@"resolve": resolve,
|
|
909
|
+
@"reject": reject,
|
|
910
|
+
@"tempFile": tempFilePath
|
|
911
|
+
};
|
|
862
912
|
self.uploadUrls[uploadId] = urlString;
|
|
863
913
|
|
|
864
914
|
[task resume];
|
|
@@ -1113,9 +1163,10 @@ RCT_EXPORT_METHOD(unzip:(NSString *)sourcePath
|
|
|
1113
1163
|
// pure-Foundation approach using NSInputStream with a known zip local-file header parser.
|
|
1114
1164
|
|
|
1115
1165
|
// ── Pure-Foundation zip reader (no third-party, no subprocess) ──────────
|
|
1116
|
-
|
|
1166
|
+
NSError *readError = nil;
|
|
1167
|
+
NSData *zipData = [NSData dataWithContentsOfFile:sourcePath options:NSDataReadingMappedIfSafe error:&readError];
|
|
1117
1168
|
if (!zipData) {
|
|
1118
|
-
resolve(@{@"success": @NO, @"error": @"Cannot read zip file"});
|
|
1169
|
+
resolve(@{@"success": @NO, @"error": readError.localizedDescription ?: @"Cannot read zip file"});
|
|
1119
1170
|
return;
|
|
1120
1171
|
}
|
|
1121
1172
|
|
|
@@ -1300,7 +1351,14 @@ RCT_EXPORT_METHOD(zip:(NSString *)sourcePath
|
|
|
1300
1351
|
// Delete existing destination file
|
|
1301
1352
|
[fm removeItemAtPath:destPath error:nil];
|
|
1302
1353
|
|
|
1303
|
-
|
|
1354
|
+
// Create the destination file and open a handle for writing
|
|
1355
|
+
[fm createFileAtPath:destPath contents:nil attributes:nil];
|
|
1356
|
+
NSFileHandle *fh = [NSFileHandle fileHandleForWritingAtPath:destPath];
|
|
1357
|
+
if (!fh) {
|
|
1358
|
+
resolve(@{@"success": @NO, @"error": @"Failed to create destination zip file"});
|
|
1359
|
+
return;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1304
1362
|
NSMutableArray<NSDictionary *> *centralDirectory = [NSMutableArray new];
|
|
1305
1363
|
|
|
1306
1364
|
NSArray<NSString *> *filesToZip;
|
|
@@ -1310,9 +1368,6 @@ RCT_EXPORT_METHOD(zip:(NSString *)sourcePath
|
|
|
1310
1368
|
NSMutableArray *files = [NSMutableArray new];
|
|
1311
1369
|
NSString *file;
|
|
1312
1370
|
while ((file = [enumerator nextObject])) {
|
|
1313
|
-
NSString *fullPath = [sourcePath stringByAppendingPathComponent:file];
|
|
1314
|
-
BOOL entryIsDir = NO;
|
|
1315
|
-
[fm fileExistsAtPath:fullPath isDirectory:&entryIsDir];
|
|
1316
1371
|
[files addObject:file];
|
|
1317
1372
|
}
|
|
1318
1373
|
filesToZip = files;
|
|
@@ -1327,80 +1382,138 @@ RCT_EXPORT_METHOD(zip:(NSString *)sourcePath
|
|
|
1327
1382
|
BOOL entryIsDir = NO;
|
|
1328
1383
|
[fm fileExistsAtPath:fullPath isDirectory:&entryIsDir];
|
|
1329
1384
|
|
|
1330
|
-
NSData *fileData = entryIsDir ? [NSData data] : [NSData dataWithContentsOfFile:fullPath];
|
|
1331
|
-
if (!fileData) continue;
|
|
1332
|
-
|
|
1333
1385
|
NSData *entryNameData = [relativePath dataUsingEncoding:NSUTF8StringEncoding];
|
|
1334
1386
|
uint16_t nameLen = (uint16_t)entryNameData.length;
|
|
1335
1387
|
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1388
|
+
uint32_t localHeaderOffset = (uint32_t)[fh offsetInFile];
|
|
1389
|
+
|
|
1390
|
+
// Write local file header with placeholder CRC/sizes
|
|
1391
|
+
uint32_t sig = CFSwapInt32HostToLittle(0x04034b50);
|
|
1392
|
+
uint16_t version = CFSwapInt16HostToLittle(20);
|
|
1393
|
+
uint16_t flags = 0;
|
|
1394
|
+
uint16_t modTime = 0, modDate = 0;
|
|
1395
|
+
uint16_t extraLen = 0;
|
|
1396
|
+
|
|
1397
|
+
// Placeholders — will be patched after streaming
|
|
1398
|
+
uint16_t method = 0;
|
|
1399
|
+
uint32_t crcLE = 0;
|
|
1400
|
+
uint32_t compSz = 0;
|
|
1401
|
+
uint32_t uncompSz = 0;
|
|
1402
|
+
|
|
1403
|
+
[fh writeData:[NSData dataWithBytes:&sig length:4]];
|
|
1404
|
+
[fh writeData:[NSData dataWithBytes:&version length:2]];
|
|
1405
|
+
[fh writeData:[NSData dataWithBytes:&flags length:2]];
|
|
1406
|
+
[fh writeData:[NSData dataWithBytes:&method length:2]]; // offset +8
|
|
1407
|
+
[fh writeData:[NSData dataWithBytes:&modTime length:2]];
|
|
1408
|
+
[fh writeData:[NSData dataWithBytes:&modDate length:2]];
|
|
1409
|
+
[fh writeData:[NSData dataWithBytes:&crcLE length:4]]; // offset +14
|
|
1410
|
+
[fh writeData:[NSData dataWithBytes:&compSz length:4]]; // offset +18
|
|
1411
|
+
[fh writeData:[NSData dataWithBytes:&uncompSz length:4]]; // offset +22
|
|
1412
|
+
[fh writeData:[NSData dataWithBytes:&nameLen length:2]];
|
|
1413
|
+
[fh writeData:[NSData dataWithBytes:&extraLen length:2]];
|
|
1414
|
+
[fh writeData:entryNameData];
|
|
1415
|
+
|
|
1339
1416
|
uint32_t crc = 0;
|
|
1417
|
+
uint32_t compressedSize = 0;
|
|
1418
|
+
uint32_t uncompressedSize = 0;
|
|
1419
|
+
uint16_t compressionMethod = 0;
|
|
1340
1420
|
|
|
1341
|
-
if (entryIsDir
|
|
1342
|
-
|
|
1343
|
-
method = 0;
|
|
1421
|
+
if (entryIsDir) {
|
|
1422
|
+
// Directory entry — no data to write
|
|
1344
1423
|
} else {
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1424
|
+
NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:fullPath];
|
|
1425
|
+
[inputStream open];
|
|
1426
|
+
|
|
1427
|
+
if (!inputStream || inputStream.streamStatus == NSStreamStatusError) {
|
|
1428
|
+
[inputStream close];
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// Stream-compress with zlib deflate
|
|
1348
1433
|
z_stream strm;
|
|
1349
1434
|
memset(&strm, 0, sizeof(strm));
|
|
1350
|
-
strm.next_in = (Bytef *)fileData.bytes;
|
|
1351
|
-
strm.avail_in = (uInt)fileData.length;
|
|
1352
|
-
strm.next_out = (Bytef *)comp.mutableBytes;
|
|
1353
|
-
strm.avail_out = (uInt)bound;
|
|
1354
1435
|
deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
|
|
1355
|
-
|
|
1436
|
+
|
|
1437
|
+
uint8_t inBuf[32768];
|
|
1438
|
+
uint8_t outBuf[32768];
|
|
1439
|
+
int flush = Z_NO_FLUSH;
|
|
1440
|
+
|
|
1441
|
+
while ([inputStream hasBytesAvailable]) {
|
|
1442
|
+
NSInteger bytesRead = [inputStream read:inBuf maxLength:sizeof(inBuf)];
|
|
1443
|
+
if (bytesRead <= 0) break;
|
|
1444
|
+
|
|
1445
|
+
crc = (uint32_t)crc32((uLong)crc, inBuf, (uInt)bytesRead);
|
|
1446
|
+
uncompressedSize += (uint32_t)bytesRead;
|
|
1447
|
+
|
|
1448
|
+
strm.next_in = inBuf;
|
|
1449
|
+
strm.avail_in = (uInt)bytesRead;
|
|
1450
|
+
|
|
1451
|
+
if (![inputStream hasBytesAvailable]) {
|
|
1452
|
+
flush = Z_FINISH;
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
do {
|
|
1456
|
+
strm.next_out = outBuf;
|
|
1457
|
+
strm.avail_out = sizeof(outBuf);
|
|
1458
|
+
deflate(&strm, flush);
|
|
1459
|
+
NSUInteger produced = sizeof(outBuf) - strm.avail_out;
|
|
1460
|
+
if (produced > 0) {
|
|
1461
|
+
[fh writeData:[NSData dataWithBytes:outBuf length:produced]];
|
|
1462
|
+
compressedSize += (uint32_t)produced;
|
|
1463
|
+
}
|
|
1464
|
+
} while (strm.avail_out == 0);
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// Finalize deflate if we didn't hit Z_FINISH yet
|
|
1468
|
+
if (flush != Z_FINISH) {
|
|
1469
|
+
strm.next_in = NULL;
|
|
1470
|
+
strm.avail_in = 0;
|
|
1471
|
+
do {
|
|
1472
|
+
strm.next_out = outBuf;
|
|
1473
|
+
strm.avail_out = sizeof(outBuf);
|
|
1474
|
+
deflate(&strm, Z_FINISH);
|
|
1475
|
+
NSUInteger produced = sizeof(outBuf) - strm.avail_out;
|
|
1476
|
+
if (produced > 0) {
|
|
1477
|
+
[fh writeData:[NSData dataWithBytes:outBuf length:produced]];
|
|
1478
|
+
compressedSize += (uint32_t)produced;
|
|
1479
|
+
}
|
|
1480
|
+
} while (strm.avail_out == 0);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1356
1483
|
deflateEnd(&strm);
|
|
1357
|
-
[
|
|
1358
|
-
|
|
1359
|
-
method = 8;
|
|
1484
|
+
[inputStream close];
|
|
1485
|
+
compressionMethod = 8;
|
|
1360
1486
|
}
|
|
1361
1487
|
|
|
1362
|
-
//
|
|
1363
|
-
|
|
1488
|
+
// Patch the local file header with actual CRC, sizes, method
|
|
1489
|
+
unsigned long long currentPos = [fh offsetInFile];
|
|
1490
|
+
uint16_t methLE = CFSwapInt16HostToLittle(compressionMethod);
|
|
1491
|
+
uint32_t crcPatch = CFSwapInt32HostToLittle(crc);
|
|
1492
|
+
uint32_t csPatch = CFSwapInt32HostToLittle(compressedSize);
|
|
1493
|
+
uint32_t usPatch = CFSwapInt32HostToLittle(uncompressedSize);
|
|
1364
1494
|
|
|
1365
|
-
|
|
1495
|
+
[fh seekToFileOffset:localHeaderOffset + 8];
|
|
1496
|
+
[fh writeData:[NSData dataWithBytes:&methLE length:2]];
|
|
1497
|
+
[fh seekToFileOffset:localHeaderOffset + 10]; // skip modTime
|
|
1498
|
+
[fh seekToFileOffset:localHeaderOffset + 14];
|
|
1499
|
+
[fh writeData:[NSData dataWithBytes:&crcPatch length:4]];
|
|
1500
|
+
[fh writeData:[NSData dataWithBytes:&csPatch length:4]];
|
|
1501
|
+
[fh writeData:[NSData dataWithBytes:&usPatch length:4]];
|
|
1366
1502
|
|
|
1367
|
-
//
|
|
1368
|
-
uint32_t sig = CFSwapInt32HostToLittle(0x04034b50);
|
|
1369
|
-
uint16_t version = CFSwapInt16HostToLittle(20);
|
|
1370
|
-
uint16_t flags = 0;
|
|
1371
|
-
uint16_t meth = CFSwapInt16HostToLittle(method);
|
|
1372
|
-
uint16_t modTime = 0, modDate = 0; // no time for simplicity
|
|
1373
|
-
uint32_t crcLE = CFSwapInt32HostToLittle(crc);
|
|
1374
|
-
uint32_t compSz = CFSwapInt32HostToLittle((uint32_t)compressedData.length);
|
|
1375
|
-
uint32_t uncompSz = CFSwapInt32HostToLittle((uint32_t)fileData.length);
|
|
1376
|
-
uint16_t extraLen = 0;
|
|
1377
|
-
|
|
1378
|
-
[zipData appendBytes:&sig length:4];
|
|
1379
|
-
[zipData appendBytes:&version length:2];
|
|
1380
|
-
[zipData appendBytes:&flags length:2];
|
|
1381
|
-
[zipData appendBytes:&meth length:2];
|
|
1382
|
-
[zipData appendBytes:&modTime length:2];
|
|
1383
|
-
[zipData appendBytes:&modDate length:2];
|
|
1384
|
-
[zipData appendBytes:&crcLE length:4];
|
|
1385
|
-
[zipData appendBytes:&compSz length:4];
|
|
1386
|
-
[zipData appendBytes:&uncompSz length:4];
|
|
1387
|
-
[zipData appendBytes:&nameLen length:2];
|
|
1388
|
-
[zipData appendBytes:&extraLen length:2];
|
|
1389
|
-
[zipData appendData:entryNameData];
|
|
1390
|
-
[zipData appendData:compressedData];
|
|
1503
|
+
[fh seekToFileOffset:currentPos]; // restore position
|
|
1391
1504
|
|
|
1392
1505
|
[centralDirectory addObject:@{
|
|
1393
1506
|
@"name": entryNameData,
|
|
1394
|
-
@"method": @(
|
|
1507
|
+
@"method": @(compressionMethod),
|
|
1395
1508
|
@"crc": @(crc),
|
|
1396
|
-
@"compSize": @(
|
|
1397
|
-
@"uncompSize": @(
|
|
1509
|
+
@"compSize": @(compressedSize),
|
|
1510
|
+
@"uncompSize": @(uncompressedSize),
|
|
1398
1511
|
@"localOffset": @(localHeaderOffset),
|
|
1399
1512
|
}];
|
|
1400
1513
|
}
|
|
1401
1514
|
|
|
1402
1515
|
// Central directory
|
|
1403
|
-
uint32_t cdOffset = (uint32_t)
|
|
1516
|
+
uint32_t cdOffset = (uint32_t)[fh offsetInFile];
|
|
1404
1517
|
for (NSDictionary *entry in centralDirectory) {
|
|
1405
1518
|
NSData *nameData = entry[@"name"];
|
|
1406
1519
|
uint16_t nameLen = (uint16_t)nameData.length;
|
|
@@ -1419,27 +1532,27 @@ RCT_EXPORT_METHOD(zip:(NSString *)sourcePath
|
|
|
1419
1532
|
uint32_t extAttr = 0;
|
|
1420
1533
|
uint32_t localOff = CFSwapInt32HostToLittle((uint32_t)[entry[@"localOffset"] unsignedIntValue]);
|
|
1421
1534
|
|
|
1422
|
-
[
|
|
1423
|
-
[
|
|
1424
|
-
[
|
|
1425
|
-
[
|
|
1426
|
-
[
|
|
1427
|
-
[
|
|
1428
|
-
[
|
|
1429
|
-
[
|
|
1430
|
-
[
|
|
1431
|
-
[
|
|
1432
|
-
[
|
|
1433
|
-
[
|
|
1434
|
-
[
|
|
1435
|
-
[
|
|
1436
|
-
[
|
|
1437
|
-
[
|
|
1438
|
-
[
|
|
1439
|
-
[
|
|
1535
|
+
[fh writeData:[NSData dataWithBytes:&cdSig length:4]];
|
|
1536
|
+
[fh writeData:[NSData dataWithBytes:&verMade length:2]];
|
|
1537
|
+
[fh writeData:[NSData dataWithBytes:&verNeeded length:2]];
|
|
1538
|
+
[fh writeData:[NSData dataWithBytes:&flags length:2]];
|
|
1539
|
+
[fh writeData:[NSData dataWithBytes:&meth length:2]];
|
|
1540
|
+
[fh writeData:[NSData dataWithBytes:&modTime length:2]];
|
|
1541
|
+
[fh writeData:[NSData dataWithBytes:&modDate length:2]];
|
|
1542
|
+
[fh writeData:[NSData dataWithBytes:&crcLE length:4]];
|
|
1543
|
+
[fh writeData:[NSData dataWithBytes:&compSz length:4]];
|
|
1544
|
+
[fh writeData:[NSData dataWithBytes:&uncompSz length:4]];
|
|
1545
|
+
[fh writeData:[NSData dataWithBytes:&nameLen length:2]];
|
|
1546
|
+
[fh writeData:[NSData dataWithBytes:&extraLen length:2]];
|
|
1547
|
+
[fh writeData:[NSData dataWithBytes:&commentLen length:2]];
|
|
1548
|
+
[fh writeData:[NSData dataWithBytes:&disk length:2]];
|
|
1549
|
+
[fh writeData:[NSData dataWithBytes:&intAttr length:2]];
|
|
1550
|
+
[fh writeData:[NSData dataWithBytes:&extAttr length:4]];
|
|
1551
|
+
[fh writeData:[NSData dataWithBytes:&localOff length:4]];
|
|
1552
|
+
[fh writeData:nameData];
|
|
1440
1553
|
}
|
|
1441
1554
|
|
|
1442
|
-
uint32_t cdSize = CFSwapInt32HostToLittle((uint32_t)(
|
|
1555
|
+
uint32_t cdSize = CFSwapInt32HostToLittle((uint32_t)([fh offsetInFile] - cdOffset));
|
|
1443
1556
|
uint32_t cdOffLE = CFSwapInt32HostToLittle(cdOffset);
|
|
1444
1557
|
uint16_t numEntries = CFSwapInt16HostToLittle((uint16_t)centralDirectory.count);
|
|
1445
1558
|
uint16_t commentLen = 0;
|
|
@@ -1447,21 +1560,17 @@ RCT_EXPORT_METHOD(zip:(NSString *)sourcePath
|
|
|
1447
1560
|
// End of central directory record
|
|
1448
1561
|
uint32_t eocdSig = CFSwapInt32HostToLittle(0x06054b50);
|
|
1449
1562
|
uint16_t disk = 0;
|
|
1450
|
-
[
|
|
1451
|
-
[
|
|
1452
|
-
[
|
|
1453
|
-
[
|
|
1454
|
-
[
|
|
1455
|
-
[
|
|
1456
|
-
[
|
|
1457
|
-
[
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
resolve(@{@"success": @YES, @"zipPath": destPath});
|
|
1462
|
-
} else {
|
|
1463
|
-
resolve(@{@"success": @NO, @"error": writeErr.localizedDescription ?: @"ZIP_WRITE_ERROR"});
|
|
1464
|
-
}
|
|
1563
|
+
[fh writeData:[NSData dataWithBytes:&eocdSig length:4]];
|
|
1564
|
+
[fh writeData:[NSData dataWithBytes:&disk length:2]];
|
|
1565
|
+
[fh writeData:[NSData dataWithBytes:&disk length:2]];
|
|
1566
|
+
[fh writeData:[NSData dataWithBytes:&numEntries length:2]];
|
|
1567
|
+
[fh writeData:[NSData dataWithBytes:&numEntries length:2]];
|
|
1568
|
+
[fh writeData:[NSData dataWithBytes:&cdSize length:4]];
|
|
1569
|
+
[fh writeData:[NSData dataWithBytes:&cdOffLE length:4]];
|
|
1570
|
+
[fh writeData:[NSData dataWithBytes:&commentLen length:2]];
|
|
1571
|
+
|
|
1572
|
+
[fh closeFile];
|
|
1573
|
+
resolve(@{@"success": @YES, @"zipPath": destPath});
|
|
1465
1574
|
});
|
|
1466
1575
|
}
|
|
1467
1576
|
|