2
0
mirror of synced 2025-02-12 14:26:46 +00:00

[storage][ios] fix automatic mime/content type detection for storage meta

This commit is contained in:
Salakar 2018-07-07 03:10:35 +01:00
parent d59ee569b6
commit c13c81f36d
4 changed files with 82 additions and 122 deletions

View File

@ -601,12 +601,10 @@ public class RNFirebaseStorage extends ReactContextBaseJavaModule {
*/ */
private void sendJSEvent(String appName, final String name, final String path, WritableMap body) { private void sendJSEvent(String appName, final String name, final String path, WritableMap body) {
WritableMap event = Arguments.createMap(); WritableMap event = Arguments.createMap();
event.putString("appName", appName);
event.putString("eventName", name);
event.putString("path", path);
event.putMap("body", body); event.putMap("body", body);
event.putString("path", path);
event.putString("eventName", name);
event.putString("appName", appName);
Utils.sendEvent(this.getReactApplicationContext(), STORAGE_EVENT, event); Utils.sendEvent(this.getReactApplicationContext(), STORAGE_EVENT, event);
} }

View File

@ -55,18 +55,18 @@ PODS:
- FirebaseAnalytics (5.0.1): - FirebaseAnalytics (5.0.1):
- FirebaseCore (~> 5.0) - FirebaseCore (~> 5.0)
- FirebaseInstanceID (~> 3.0) - FirebaseInstanceID (~> 3.0)
- GoogleToolboxForMac/NSData+zlib (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- nanopb (~> 0.3) - nanopb (~> 0.3)
- FirebaseAuth (5.0.1): - FirebaseAuth (5.0.1):
- FirebaseCore (~> 5.0) - FirebaseCore (~> 5.0)
- GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Core (~> 1.1)
- FirebaseCore (5.0.4): - FirebaseCore (5.0.4):
- GoogleToolboxForMac/NSData+zlib (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- FirebaseCrash (3.0.0): - FirebaseCrash (3.0.0):
- FirebaseAnalytics (~> 5.0) - FirebaseAnalytics (~> 5.0)
- FirebaseInstanceID (~> 3.0) - FirebaseInstanceID (~> 3.0)
- GoogleToolboxForMac/Logger (~> 2.1) - GoogleToolboxForMac/Logger (~> 2.1)
- GoogleToolboxForMac/NSData+zlib (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- Protobuf (~> 3.5) - Protobuf (~> 3.5)
- FirebaseDatabase (5.0.1): - FirebaseDatabase (5.0.1):
- FirebaseCore (~> 5.0) - FirebaseCore (~> 5.0)
@ -95,8 +95,8 @@ PODS:
- GoogleAPIClientForREST (~> 1.0) - GoogleAPIClientForREST (~> 1.0)
- GoogleSignIn (~> 4.1) - GoogleSignIn (~> 4.1)
- GoogleToolboxForMac/Logger (~> 2.1) - GoogleToolboxForMac/Logger (~> 2.1)
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1) - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1) - "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- GoogleToolboxForMac/StringEncoding (~> 2.1) - GoogleToolboxForMac/StringEncoding (~> 2.1)
- GoogleToolboxForMac/URLBuilder (~> 2.1) - GoogleToolboxForMac/URLBuilder (~> 2.1)
- GTMOAuth2 (~> 1.0) - GTMOAuth2 (~> 1.0)
@ -114,7 +114,7 @@ PODS:
- FirebaseSwizzlingUtilities/ISASwizzling (~> 2.0) - FirebaseSwizzlingUtilities/ISASwizzling (~> 2.0)
- FirebaseSwizzlingUtilities/MethodSwizzling (~> 2.0) - FirebaseSwizzlingUtilities/MethodSwizzling (~> 2.0)
- GoogleToolboxForMac/Logger (~> 2.1) - GoogleToolboxForMac/Logger (~> 2.1)
- GoogleToolboxForMac/NSData+zlib (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Core (~> 1.1)
- Protobuf (~> 3.5) - Protobuf (~> 3.5)
- FirebaseRemoteConfig (3.0.0): - FirebaseRemoteConfig (3.0.0):
@ -122,7 +122,7 @@ PODS:
- FirebaseAnalytics (~> 5.0) - FirebaseAnalytics (~> 5.0)
- FirebaseCore (~> 5.0) - FirebaseCore (~> 5.0)
- FirebaseInstanceID (~> 3.0) - FirebaseInstanceID (~> 3.0)
- GoogleToolboxForMac/NSData+zlib (~> 2.1) - "GoogleToolboxForMac/NSData+zlib (~> 2.1)"
- Protobuf (~> 3.5) - Protobuf (~> 3.5)
- FirebaseStorage (3.0.0): - FirebaseStorage (3.0.0):
- FirebaseCore (~> 5.0) - FirebaseCore (~> 5.0)
@ -137,8 +137,8 @@ PODS:
- GoogleAPIClientForREST/Core (1.3.4): - GoogleAPIClientForREST/Core (1.3.4):
- GTMSessionFetcher (>= 1.1.7) - GTMSessionFetcher (>= 1.1.7)
- GoogleSignIn (4.1.2): - GoogleSignIn (4.1.2):
- GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1) - "GoogleToolboxForMac/NSDictionary+URLArguments (~> 2.1)"
- GoogleToolboxForMac/NSString+URLArguments (~> 2.1) - "GoogleToolboxForMac/NSString+URLArguments (~> 2.1)"
- GTMOAuth2 (~> 1.0) - GTMOAuth2 (~> 1.0)
- GTMSessionFetcher/Core (~> 1.1) - GTMSessionFetcher/Core (~> 1.1)
- GoogleToolboxForMac/Core (2.1.4): - GoogleToolboxForMac/Core (2.1.4):
@ -148,20 +148,20 @@ PODS:
- GoogleToolboxForMac/Defines (2.1.4) - GoogleToolboxForMac/Defines (2.1.4)
- GoogleToolboxForMac/Logger (2.1.4): - GoogleToolboxForMac/Logger (2.1.4):
- GoogleToolboxForMac/Defines (= 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/Defines (= 2.1.4)
- GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4): - "GoogleToolboxForMac/NSDictionary+URLArguments (2.1.4)":
- GoogleToolboxForMac/DebugUtils (= 2.1.4) - GoogleToolboxForMac/DebugUtils (= 2.1.4)
- GoogleToolboxForMac/Defines (= 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/StringEncoding (2.1.4):
- GoogleToolboxForMac/Defines (= 2.1.4) - GoogleToolboxForMac/Defines (= 2.1.4)
- GoogleToolboxForMac/URLBuilder (2.1.4): - GoogleToolboxForMac/URLBuilder (2.1.4):
- GoogleToolboxForMac/Core (= 2.1.4) - GoogleToolboxForMac/Core (= 2.1.4)
- GoogleToolboxForMac/Defines (= 2.1.4) - GoogleToolboxForMac/Defines (= 2.1.4)
- GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4) - "GoogleToolboxForMac/NSDictionary+URLArguments (= 2.1.4)"
- GoogleToolboxForMac/NSString+URLArguments (= 2.1.4) - "GoogleToolboxForMac/NSString+URLArguments (= 2.1.4)"
- gRPC (1.12.0): - gRPC (1.12.0):
- gRPC-RxLibrary (= 1.12.0) - gRPC-RxLibrary (= 1.12.0)
- gRPC/Main (= 1.12.0) - gRPC/Main (= 1.12.0)
@ -238,13 +238,49 @@ DEPENDENCIES:
- RNFirebase (from `../../ios/RNFirebase.podspec`) - RNFirebase (from `../../ios/RNFirebase.podspec`)
- yoga (from `../node_modules/react-native/ReactCommon/yoga`) - 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: EXTERNAL SOURCES:
React: React:
:path: ../node_modules/react-native :path: "../node_modules/react-native"
RNFirebase: RNFirebase:
:path: ../../ios/RNFirebase.podspec :path: "../../ios/RNFirebase.podspec"
yoga: yoga:
:path: ../node_modules/react-native/ReactCommon/yoga :path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS: SPEC CHECKSUMS:
BoringSSL: cf3f1793eb6e3c445c4d150456341f149c268a35 BoringSSL: cf3f1793eb6e3c445c4d150456341f149c268a35
@ -286,4 +322,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 582ceaad051470812ad9203e13b5ea8ad20c78ac PODFILE CHECKSUM: 582ceaad051470812ad9203e13b5ea8ad20c78ac
COCOAPODS: 1.4.0 COCOAPODS: 1.5.3

View File

@ -595,7 +595,6 @@
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
CC0F353E1D461097008BB94F /* Embed Frameworks */, CC0F353E1D461097008BB94F /* Embed Frameworks */,
7D57265F10EEF7CD92D7973F /* Copy Detox Framework */, 7D57265F10EEF7CD92D7973F /* Copy Detox Framework */,
4EEB648E968FA6F093B42978 /* [CP] Embed Pods Frameworks */,
CC8D61273332DE7812CFF010 /* [CP] Copy Pods Resources */, CC8D61273332DE7812CFF010 /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
@ -971,21 +970,6 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.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 */ = { 7D57265F10EEF7CD92D7973F /* Copy Detox Framework */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;

View File

@ -209,91 +209,33 @@ RCT_EXPORT_METHOD(putFile:(NSString *) appDisplayName
metadata:(NSDictionary *) metadata metadata:(NSDictionary *) metadata
resolver:(RCTPromiseResolveBlock) resolve resolver:(RCTPromiseResolveBlock) resolve
rejecter:(RCTPromiseRejectBlock) reject) { rejecter:(RCTPromiseRejectBlock) 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]; FIRStorageMetadata *firmetadata = [self buildMetadataFromMap:metadata];
if ([localPath hasPrefix:@"assets-library://"] || [localPath hasPrefix:@"ph://"]) {
PHFetchResult *assets;
if ([localPath hasPrefix:@"assets-library://"]) { if ([firmetadata valueForKey:@"contentType"] == nil) {
NSURL *localFile = [[NSURL alloc] initWithString:localPath]; firmetadata.contentType = [self mimeTypeForPath:localPath];
assets = [PHAsset fetchAssetsWithALAssetURLs:@[localFile] options:nil];
} else {
NSString *assetId = [localPath substringFromIndex:@"ph://".length];
assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetId] options:nil];
} }
PHAsset *asset = [assets firstObject]; // TODO convert heic -> jpeg only if users asks for it
// 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]; [self uploadData:appDisplayName data:data firmetadata:firmetadata path:path resolver:resolve rejecter:reject];
} }
- (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";
} }
- (NSURL *)temporaryFileUrl { return (__bridge_transfer NSString *) mimeType;
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);
} }
- (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject { - (void)uploadFile:(NSString *)appDisplayName url:(NSURL *)url firmetadata:(FIRStorageMetadata *)firmetadata path:(NSString *)path resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {