[storage][ios] fix automatic mime/content type detection for storage meta
This commit is contained in:
parent
d59ee569b6
commit
c13c81f36d
@ -601,12 +601,10 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
private void sendJSEvent(String appName, final String name, final String path, WritableMap body) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
|
||||
event.putString("appName", appName);
|
||||
event.putString("eventName", name);
|
||||
event.putString("path", path);
|
||||
event.putMap("body", body);
|
||||
|
||||
event.putString("path", path);
|
||||
event.putString("eventName", name);
|
||||
event.putString("appName", appName);
|
||||
Utils.sendEvent(this.getReactApplicationContext(), STORAGE_EVENT, event);
|
||||
}
|
||||
|
||||
|
@ -55,18 +55,18 @@ PODS:
|
||||
- FirebaseAnalytics (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- nanopb (~> 0.3)
|
||||
- FirebaseAuth (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- FirebaseCore (5.0.4):
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- FirebaseCrash (3.0.0):
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseDatabase (5.0.1):
|
||||
- FirebaseCore (~> 5.0)
|
||||
@ -95,8 +95,8 @@ PODS:
|
||||
- GoogleAPIClientForREST (~> 1.0)
|
||||
- GoogleSignIn (~> 4.1)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
|
||||
- GoogleToolboxForMac/StringEncoding (~> 2.1)
|
||||
- GoogleToolboxForMac/URLBuilder (~> 2.1)
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
@ -114,7 +114,7 @@ PODS:
|
||||
- FirebaseSwizzlingUtilities/ISASwizzling (~> 2.0)
|
||||
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 2.0)
|
||||
- GoogleToolboxForMac/Logger (~> 2.1)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseRemoteConfig (3.0.0):
|
||||
@ -122,7 +122,7 @@ PODS:
|
||||
- FirebaseAnalytics (~> 5.0)
|
||||
- FirebaseCore (~> 5.0)
|
||||
- FirebaseInstanceID (~> 3.0)
|
||||
- GoogleToolboxForMac/NSData+zlib (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
|
||||
- Protobuf (~> 3.5)
|
||||
- FirebaseStorage (3.0.0):
|
||||
- FirebaseCore (~> 5.0)
|
||||
@ -137,8 +137,8 @@ PODS:
|
||||
- GoogleAPIClientForREST/Core (1.3.4):
|
||||
- GTMSessionFetcher (>= 1.1.7)
|
||||
- GoogleSignIn (4.1.2):
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
|
||||
- GTMOAuth2 (~> 1.0)
|
||||
- GTMSessionFetcher/Core (~> 1.1)
|
||||
- GoogleToolboxForMac/Core (2.1.4):
|
||||
@ -148,20 +148,20 @@ PODS:
|
||||
- GoogleToolboxForMac/Defines (2.1.4)
|
||||
- GoogleToolboxForMac/Logger (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSData+zlib (2.1.4):
|
||||
- "GoogleToolboxForMac/NSData+zlib (2.1.4)":
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4):
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4)":
|
||||
- GoogleToolboxForMac/DebugUtils (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (2.1.4)
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (2.1.4)"
|
||||
- GoogleToolboxForMac/StringEncoding (2.1.4):
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/URLBuilder (2.1.4):
|
||||
- GoogleToolboxForMac/Core (= 2.1.4)
|
||||
- GoogleToolboxForMac/Defines (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4)
|
||||
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)
|
||||
- "GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4)"
|
||||
- "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
|
||||
- gRPC (1.12.0):
|
||||
- gRPC-RxLibrary (= 1.12.0)
|
||||
- gRPC/Main (= 1.12.0)
|
||||
@ -238,13 +238,49 @@ DEPENDENCIES:
|
||||
- RNFirebase (from `../../ios/RNFirebase.podspec`)
|
||||
- yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/cocoapods/specs.git:
|
||||
- BoringSSL
|
||||
- Crashlytics
|
||||
- Fabric
|
||||
- Firebase
|
||||
- FirebaseABTesting
|
||||
- FirebaseAnalytics
|
||||
- FirebaseAuth
|
||||
- FirebaseCore
|
||||
- FirebaseCrash
|
||||
- FirebaseDatabase
|
||||
- FirebaseDynamicLinks
|
||||
- FirebaseFirestore
|
||||
- FirebaseFunctions
|
||||
- FirebaseInstanceID
|
||||
- FirebaseInvites
|
||||
- FirebaseMessaging
|
||||
- FirebasePerformance
|
||||
- FirebaseRemoteConfig
|
||||
- FirebaseStorage
|
||||
- FirebaseSwizzlingUtilities
|
||||
- Google-Mobile-Ads-SDK
|
||||
- GoogleAPIClientForREST
|
||||
- GoogleSignIn
|
||||
- GoogleToolboxForMac
|
||||
- gRPC
|
||||
- gRPC-Core
|
||||
- gRPC-ProtoRPC
|
||||
- gRPC-RxLibrary
|
||||
- GTMOAuth2
|
||||
- GTMSessionFetcher
|
||||
- leveldb-library
|
||||
- nanopb
|
||||
- Protobuf
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
React:
|
||||
:path: ../node_modules/react-native
|
||||
:path: "../node_modules/react-native"
|
||||
RNFirebase:
|
||||
:path: ../../ios/RNFirebase.podspec
|
||||
:path: "../../ios/RNFirebase.podspec"
|
||||
yoga:
|
||||
:path: ../node_modules/react-native/ReactCommon/yoga
|
||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
BoringSSL: cf3f1793eb6e3c445c4d150456341f149c268a35
|
||||
@ -286,4 +322,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 582ceaad051470812ad9203e13b5ea8ad20c78ac
|
||||
|
||||
COCOAPODS: 1.4.0
|
||||
COCOAPODS: 1.5.3
|
||||
|
@ -595,7 +595,6 @@
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
CC0F353E1D461097008BB94F /* Embed Frameworks */,
|
||||
7D57265F10EEF7CD92D7973F /* Copy Detox Framework */,
|
||||
4EEB648E968FA6F093B42978 /* [CP] Embed Pods Frameworks */,
|
||||
CC8D61273332DE7812CFF010 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
@ -971,21 +970,6 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh";
|
||||
};
|
||||
4EEB648E968FA6F093B42978 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-testing/Pods-testing-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7D57265F10EEF7CD92D7973F /* Copy Detox Framework */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -209,91 +209,33 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
|
||||
metadata:(NSDictionary *) metadata
|
||||
resolver:(RCTPromiseResolveBlock) resolve
|
||||
rejecter:(RCTPromiseRejectBlock) reject) {
|
||||
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
|
||||
if ([localPath hasPrefix:@"assets-library://"] || [localPath hasPrefix:@"ph://"]) {
|
||||
PHFetchResult *assets;
|
||||
|
||||
if ([localPath hasPrefix:@"assets-library://"]) {
|
||||
NSURL *localFile = [[NSURL alloc] initWithString:localPath];
|
||||
assets = [PHAsset fetchAssetsWithALAssetURLs:@[localFile] options:nil];
|
||||
} else {
|
||||
NSString *assetId = [localPath substringFromIndex:@"ph://".length];
|
||||
assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil];
|
||||
}
|
||||
|
||||
PHAsset *asset = [assets firstObject];
|
||||
|
||||
// this is based on http://stackoverflow.com/questions/35241449
|
||||
if (asset.mediaType == PHAssetMediaTypeImage) {
|
||||
// images
|
||||
PHImageRequestOptions *options = [PHImageRequestOptions new];
|
||||
options.networkAccessAllowed = true;
|
||||
[[PHImageManager defaultManager] requestImageDataForAsset:asset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
|
||||
if (info[PHImageErrorKey] == nil) {
|
||||
if (UTTypeConformsTo((__bridge CFStringRef)dataUTI, kUTTypeJPEG)) {
|
||||
firmetadata.contentType = [self utiToMimeType:dataUTI];
|
||||
[self uploadData:appDisplayName data:imageData firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
} else {
|
||||
// if the image UTI is not JPEG then convert to JPEG, e.g. HEI
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
|
||||
NSDictionary *imageInfo = (__bridge NSDictionary*)CGImageSourceCopyPropertiesAtIndex(source, 0, NULL);
|
||||
NSDictionary *imageMetadata = [imageInfo copy];
|
||||
NSMutableData *imageDataJPEG = [NSMutableData data];
|
||||
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageDataJPEG, kUTTypeJPEG, 1, NULL);
|
||||
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef)imageMetadata);
|
||||
CGImageDestinationFinalize(destination);
|
||||
// Manually set mimetype to JPEG
|
||||
firmetadata.contentType = @"image/jpeg";
|
||||
[self uploadData:appDisplayName data:[NSData dataWithData:imageDataJPEG] firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
}
|
||||
} else {
|
||||
reject(@"storage/request-image-data-failed", @"Could not obtain image data for the specified file.", nil);
|
||||
}
|
||||
}];
|
||||
} else if (asset.mediaType == PHAssetMediaTypeVideo) {
|
||||
// video
|
||||
PHVideoRequestOptions *options = [PHVideoRequestOptions new];
|
||||
options.networkAccessAllowed = true;
|
||||
[[PHImageManager defaultManager] requestExportSessionForVideo:asset options:options exportPreset:AVAssetExportPresetHighestQuality resultHandler:^(AVAssetExportSession *_Nullable exportSession, NSDictionary *_Nullable info) {
|
||||
if (info[PHImageErrorKey] == nil) {
|
||||
NSURL *tempUrl = [self temporaryFileUrl];
|
||||
exportSession.outputURL = tempUrl;
|
||||
|
||||
NSArray<PHAssetResource *> *resources = [PHAssetResource assetResourcesForAsset:asset];
|
||||
for (PHAssetResource *resource in resources) {
|
||||
exportSession.outputFileType = resource.uniformTypeIdentifier;
|
||||
if (exportSession.outputFileType != nil) break;
|
||||
}
|
||||
|
||||
[exportSession exportAsynchronouslyWithCompletionHandler:^{
|
||||
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
|
||||
firmetadata.contentType = [self utiToMimeType:exportSession.outputFileType];
|
||||
[self uploadFile:appDisplayName url:tempUrl firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
// we're not cleaning up the temporary file at the moment, just relying on the OS to do that in it's own time - todo?
|
||||
} else {
|
||||
reject(@"storage/temporary-file-failure", @"Unable to create temporary file for upload.", nil);
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
reject(@"storage/export-session-failure", @"Unable to create export session for asset.", nil);
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
// TODO: Content type for file?
|
||||
NSData *data = [[NSFileManager defaultManager] contentsAtPath:localPath];
|
||||
[self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:localPath]) {
|
||||
reject(@"storage/file-not-found", @"File specified at path does not exist.", nil);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
NSData *data = [NSData dataWithContentsOfFile:localPath];
|
||||
FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
|
||||
|
||||
if ([firmetadata valueForKey:@"contentType"] == nil) {
|
||||
firmetadata.contentType = [self mimeTypeForPath:localPath];
|
||||
}
|
||||
|
||||
// TODO convert heic -> jpeg only if users asks for it
|
||||
|
||||
[self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
|
||||
}
|
||||
|
||||
- (NSURL *)temporaryFileUrl {
|
||||
NSString *filename = [NSString stringWithFormat:@"%@.tmp", [[NSProcessInfo processInfo] globallyUniqueString]];
|
||||
return [[NSURL fileURLWithPath:NSTemporaryDirectory()] URLByAppendingPathComponent:filename];
|
||||
}
|
||||
|
||||
- (NSString *)utiToMimeType:(NSString *) dataUTI {
|
||||
return (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)dataUTI, kUTTagClassMIMEType);
|
||||
- (NSString*) mimeTypeForPath: (NSString *) path {
|
||||
CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
|
||||
CFStringRef mimeType = UTTypeCopyPreferredTagWithClass (UTI, kUTTagClassMIMEType);
|
||||
CFRelease(UTI);
|
||||
|
||||
if (!mimeType) {
|
||||
return @"application/octet-stream";
|
||||
}
|
||||
|
||||
return (__bridge_transfer NSString *) mimeType;
|
||||
}
|
||||
|
||||
- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
||||
|
Loading…
x
Reference in New Issue
Block a user