Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix image file size when uploaded from ios #10297

Merged
merged 2 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ios/NewExpensify.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
1E76D5232522316A005A268F /* GTAmericaExp-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = AE65058949E14DA5A2D5435D /* GTAmericaExp-Medium.otf */; };
1E76D5242522316A005A268F /* GTAmericaExp-Regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8C7003903C1E4957824899BB /* GTAmericaExp-Regular.otf */; };
1E76D5252522316A005A268F /* GTAmericaExp-Thin.otf in Resources */ = {isa = PBXBuildFile; fileRef = A292718541C841859D97DF2F /* GTAmericaExp-Thin.otf */; };
374FB8D728A133FE000D84EF /* OriginImageRequestHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 374FB8D628A133FE000D84EF /* OriginImageRequestHandler.mm */; };
425866037F4C482AAB46CB8B /* GTAmericaExp-BdIt.otf in Resources */ = {isa = PBXBuildFile; fileRef = A8D6F2F722FD4E66A38EBBB6 /* GTAmericaExp-BdIt.otf */; };
51A507DCDB4AFAE4CE18F09C /* libPods-NewExpensify-NewExpensifyTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F365B4C53B0AD330B82D09E5 /* libPods-NewExpensify-NewExpensifyTests.a */; };
52477A09739546F4814EA25F /* GTAmericaExpMono-Bd.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0DE5D096095C41EE96746C9E /* GTAmericaExpMono-Bd.otf */; };
Expand Down Expand Up @@ -65,6 +66,8 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NewExpensify/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NewExpensify/main.m; sourceTree = "<group>"; };
18D050DF262400AF000D658B /* BridgingFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgingFile.swift; sourceTree = "<group>"; };
374FB8D528A133A7000D84EF /* OriginImageRequestHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OriginImageRequestHandler.h; path = NewExpensify/OriginImageRequestHandler.h; sourceTree = "<group>"; };
374FB8D628A133FE000D84EF /* OriginImageRequestHandler.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = OriginImageRequestHandler.mm; path = NewExpensify/OriginImageRequestHandler.mm; sourceTree = "<group>"; };
3981452A2C7340EBBA2B9BD1 /* GTAmericaExpMono-BdIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-BdIt.otf"; path = "../assets/fonts/GTAmericaExpMono-BdIt.otf"; sourceTree = "<group>"; };
5150E5D0D7F74DBA8D7C1914 /* GTAmericaExpMono-RgIt.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GTAmericaExpMono-RgIt.otf"; path = "../assets/fonts/GTAmericaExpMono-RgIt.otf"; sourceTree = "<group>"; };
5DADA231C0DAA1842EE3E945 /* Pods-NewExpensify-NewExpensifyTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -169,6 +172,8 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
374FB8D528A133A7000D84EF /* OriginImageRequestHandler.h */,
374FB8D628A133FE000D84EF /* OriginImageRequestHandler.mm */,
F0C450E92705020500FD2970 /* colors.json */,
DD7904292792E76D004484B4 /* RCTBootSplash.h */,
DD79042A2792E76D004484B4 /* RCTBootSplash.m */,
Expand Down Expand Up @@ -582,6 +587,7 @@
files = (
18D050E0262400AF000D658B /* BridgingFile.swift in Sources */,
0F5E5350263B73FD004CA14F /* EnvironmentChecker.m in Sources */,
374FB8D728A133FE000D84EF /* OriginImageRequestHandler.mm in Sources */,
7041848526A8E47D00E09F4D /* RCTStartupTimer.m in Sources */,
DD79042B2792E76D004484B4 /* RCTBootSplash.m in Sources */,
0CDA8E34287DD650004ECBEC /* AppDelegate.mm in Sources */,
Expand Down
12 changes: 12 additions & 0 deletions ios/NewExpensify/OriginImageRequestHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// OriginImageRequestHandler.h
// NewExpensify
//
// Created by ntdiary on 2022/8/8.
//

#import <React/RCTURLRequestHandler.h>

@interface OriginImageRequestHandler : NSObject <RCTURLRequestHandler>

@end
Comment on lines +1 to +12
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a header file created by convention.

131 changes: 131 additions & 0 deletions ios/NewExpensify/OriginImageRequestHandler.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
//
// OriginImageRequestHandler.mm
// NewExpensify
//
// Created by ntdiary on 2022/8/8.
//
// Use this handler to parse images uri returned by react-native-image-picker
// instead of the default `RCTImageLoader.mm`
// See https://github.com/facebook/react-native/issues/33760#issuecomment-1196562161

#import <Foundation/Foundation.h>
#import <ReactCommon/RCTTurboModule.h>

#import <MobileCoreServices/MobileCoreServices.h>
#import <React/RCTUtils.h>

#import "OriginImageRequestHandler.h"

@interface OriginImageRequestHandler() <RCTTurboModule>

@end

@implementation OriginImageRequestHandler
{
NSOperationQueue *_fileQueue;
}

RCT_EXPORT_MODULE()

- (void)invalidate
{
[_fileQueue cancelAllOperations];
_fileQueue = nil;
}

Comment on lines +23 to +35
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this handler needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in my proposal, the issue root cause is UIImageJPEGRepresentation and UIImagePNGRepresentation.

these functions will change the image binary data when selecting and uploading.
...
for react-native-image-picker, can submit a PR with adding a option to keep origin data.
for react-native, can customize a new handler to deal the image upload.

We need to use this handler to upload the image file instead of the default RCTImageLoader.mm,
because the RCTImageLoader.mm also uses the above two functions.

/**
* Only used for parsing the png/jpg image in the application home directory
*/
- (BOOL)canHandleRequest:(NSURLRequest *)request
{
return [request.URL.scheme caseInsensitiveCompare:@"file"] == NSOrderedSame
&& RCTIsLocalAssetURL(request.URL)
&& !RCTIsBundleAssetURL(request.URL);
}


/**
* Send a network request and call the delegate with the response data.
*/
- (NSOperation *)sendRequest:(NSURLRequest *)request
withDelegate:(id<RCTURLRequestDelegate>)delegate
{
// Lazy setup
if (!_fileQueue) {
_fileQueue = [NSOperationQueue new];
_fileQueue.maxConcurrentOperationCount = 4;
}

__weak __block NSBlockOperation *weakOp;
__block NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{

// Get content length
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager new];
NSDictionary<NSString *, id> *fileAttributes = [fileManager attributesOfItemAtPath:request.URL.path error:&error];
if (!fileAttributes) {
[delegate URLRequest:weakOp didCompleteWithError:error];
return;
}

// Get mime type
NSString *fileExtension = [request.URL pathExtension];
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(
kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL);
NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(
(__bridge CFStringRef)UTI, kUTTagClassMIMEType);

// Send response
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:request.URL
MIMEType:contentType
expectedContentLength:[fileAttributes[NSFileSize] ?: @-1 integerValue]
textEncodingName:nil];

[delegate URLRequest:weakOp didReceiveResponse:response];

// Load data
NSData *data = [NSData dataWithContentsOfURL:request.URL
options:NSDataReadingMappedIfSafe
error:&error];
if (data) {
[delegate URLRequest:weakOp didReceiveData:data];
}
[delegate URLRequest:weakOp didCompleteWithError:error];
}];

weakOp = op;
[_fileQueue addOperation:op];
return op;
}

/**
* Cancel the request
*/
- (void)cancelRequest:(NSOperation *)op
{
[op cancel];
}

/**
* Should return nullptr. This method may be used later to support C++ TurboModules.
* See https://reactnative.dev/docs/new-architecture-app-modules-ios
*/
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return nullptr;
}

/**
* Should have higher priority than RCTImageLoader.mm
*/
- (float)handlerPriority
{
return 4;
}

@end

Class OriginImageRequestHandlerCls(void) {
return OriginImageRequestHandler.class;
}
4 changes: 2 additions & 2 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ PODS:
- React-Core
- react-native-image-manipulator (1.0.5):
- React
- react-native-image-picker (4.7.3):
- react-native-image-picker (4.8.5):
- React-Core
- react-native-netinfo (8.3.0):
- React-Core
Expand Down Expand Up @@ -972,7 +972,7 @@ SPEC CHECKSUMS:
react-native-document-picker: 772d04a4bc5c35da9abe27b08ac271420ae3f9ef
react-native-flipper: 4bfe0a324e663f1ae2f76ad0da75673de6895efe
react-native-image-manipulator: db28c0cc09d89e740974c9bb2f13175eb48f1ef2
react-native-image-picker: ae1202414bd5c37c00b2a701daa5b6194a06b7d9
react-native-image-picker: 24a36044140202085113ce99b57bf52c62dc339e
react-native-netinfo: ebbcd8fbe1a0ce7035e43cd18c5a545dcb93dd08
react-native-pdf: 33c622cbdf776a649929e8b9d1ce2d313347c4fa
react-native-plaid-link-sdk: 9e0ebdaed648a237b36d5f6f6292b5147af92da7
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"react-native-google-places-autocomplete": "git+https://github.com/Expensify/react-native-google-places-autocomplete.git#3bbd17d63e6c38d38d857b50f6037c1c0376ff06",
"react-native-haptic-feedback": "^1.13.0",
"react-native-image-pan-zoom": "^2.1.12",
"react-native-image-picker": "^4.7.3",
"react-native-image-picker": "^4.8.5",
"react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#6b5ab5110dc3ed554f8eafbc38d7d87c17147972",
"react-native-modal": "^13.0.0",
"react-native-onyx": "1.0.10",
Expand Down