Skip to content

Commit

Permalink
Custom File Upload Controller (#1114)
Browse files Browse the repository at this point in the history
* Added pluggable PFFileUploadController protocol to PFFile.

* Added PFFile’s filename to protocol.

* Added missing implementation file for PFFileUploadResult.
Added new files to other targets.

* Converted to specifying the PFFileUploadController globally on Parse.configuration.
Created a default PFFileUploadController policy for parse-server REST upload rather than hard coding it in PFFileController.

* Backed out implementing standard upload as an implementation of PFFileUploadController; it exposed too many internals.

* Added missing private variable declaration.

* Changed copy to strong for global config reference.

* Added missing equality and copy semantics in ParseClientConfiguration.

* Marked PFFileUploadController.h as public in project.

* Marked PFFileUploadResult.h as public in project.

* Added PFFileUploadController.h and PFFileUploadResult.h to the global header file.
Changed ref to PFFileUploadController.h to a forward declaration.
  • Loading branch information
flovilmart authored Apr 7, 2017
1 parent e194a9d commit 2e21ca6
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 15 deletions.
48 changes: 48 additions & 0 deletions Parse.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

52 changes: 37 additions & 15 deletions Parse/Internal/File/Controller/PFFileController.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#import "PFMacros.h"
#import "PFRESTFileCommand.h"
#import "PFErrorUtilities.h"
#import "Parse.h"
#import "PFFileUploadController.h"

static NSString *const PFFileControllerCacheDirectoryName_ = @"PFFileCache";

Expand Down Expand Up @@ -218,21 +220,41 @@ - (NSString *)_temporaryFileDownloadPathForFileState:(PFFileState *)fileState {
return [BFTask taskWithError:error];
}

PFRESTFileCommand *command = [PFRESTFileCommand uploadCommandForFileWithName:fileState.name sessionToken:sessionToken];
@weakify(self);
return [[self.dataSource.commandRunner runFileUploadCommandAsync:command
withContentType:fileState.mimeType
contentSourceFilePath:sourceFilePath
options:PFCommandRunningOptionRetryIfFailed
cancellationToken:cancellationToken
progressBlock:progressBlock] continueWithSuccessBlock:^id(BFTask<PFCommandResult *> *task) {
@strongify(self);
PFCommandResult *result = task.result;
PFFileState *fileState = [[PFFileState alloc] initWithName:result.result[@"name"]
urlString:result.result[@"url"]
mimeType:nil];
return [[self _cacheFileAsyncWithState:fileState atPath:sourceFilePath] continueWithSuccessResult:fileState];
}];

id<PFFileUploadController> customFileUploadController = Parse.currentConfiguration.fileUploadController;
if (customFileUploadController) {
@weakify(self);
return [[customFileUploadController uploadSourceFilePath:sourceFilePath
fileName:fileState.name
mimeType:fileState.mimeType
sessionToken:sessionToken
cancellationToken:cancellationToken
progressBlock:progressBlock]
continueWithSuccessBlock:^id(BFTask<PFFileUploadResult *> *task) {
@strongify(self);
PFFileUploadResult *result = task.result;
PFFileState *fileState = [[PFFileState alloc] initWithName:result.name
urlString:result.url
mimeType:nil];
return [[self _cacheFileAsyncWithState:fileState atPath:sourceFilePath] continueWithSuccessResult:fileState];
}];
} else {
PFRESTFileCommand *command = [PFRESTFileCommand uploadCommandForFileWithName:fileState.name sessionToken:sessionToken];
@weakify(self);
return [[self.dataSource.commandRunner runFileUploadCommandAsync:command
withContentType:fileState.mimeType
contentSourceFilePath:sourceFilePath
options:PFCommandRunningOptionRetryIfFailed
cancellationToken:cancellationToken
progressBlock:progressBlock] continueWithSuccessBlock:^id(BFTask<PFCommandResult *> *task) {
@strongify(self);
PFCommandResult *result = task.result;
PFFileState *fileState = [[PFFileState alloc] initWithName:result.result[@"name"]
urlString:result.result[@"url"]
mimeType:nil];
return [[self _cacheFileAsyncWithState:fileState atPath:sourceFilePath] continueWithSuccessResult:fileState];
}];
}
}

///--------------------------------------
Expand Down
13 changes: 13 additions & 0 deletions Parse/Internal/File/Controller/PFFileUploadResult.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// PFFileUploadResult.m
// Parse
//
// Created by Ken Cooper on 2/21/17.
// Copyright © 2017 Parse Inc. All rights reserved.
//

#import "PFFileUploadResult.h"

@implementation PFFileUploadResult

@end
1 change: 1 addition & 0 deletions Parse/Internal/ParseClientConfiguration_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ extern NSString *const _ParseDefaultServerURLString;

@property (nullable, nonatomic, copy, readwrite) NSString *applicationId;
@property (nullable, nonatomic, copy, readwrite) NSString *clientKey;
@property (nullable, nonatomic, strong, readwrite) id<PFFileUploadController> fileUploadController;

@property (nonatomic, copy, readwrite) NSString *server;

Expand Down
37 changes: 37 additions & 0 deletions Parse/PFFileUploadController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// PFUploadController.h
// Parse
//
// Created by Ken Cooper on 2/20/17.
// Copyright © 2017 Parse Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <Bolts/BFTask.h>

/**
A policy interface for overriding the default upload behavior of uploading a PFFile
to application's parse server. Allows for direct uploads to other file storage
providers.
*/
@protocol PFFileUploadController <NSObject>

/**
Uploads a file asynchronously from file path for a given file state.
@param sourceFilePath Path to the file to upload.
@param fileName The PFFile's fileName.
@param mimeType The PFFile's mime type.
@param sessionToken The current users's session token.
@param cancellationToken Cancellation token.
@param progressBlock Progress block to call (optional).
@return `BFTask` with a success result set to `PFFileUploadResult` containing the url and name of the uploaded file.
*/
-(BFTask<PFFileUploadResult *> * _Nonnull)uploadSourceFilePath:(NSString * _Nonnull)sourceFilePath
fileName:(NSString * _Nullable)fileName
mimeType:(NSString * _Nullable)mimeType
sessionToken:(NSString * _Nonnull)sessionToken
cancellationToken:(BFCancellationToken * _Nonnull)cancellationToken
progressBlock:(PFProgressBlock _Nonnull)progressBlock;
@end
17 changes: 17 additions & 0 deletions Parse/PFFileUploadResult.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// PFFileUploadResult.h
// Parse
//
// Created by Ken Cooper on 2/21/17.
// Copyright © 2017 Parse Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

/**
Response provided by a custom `PFFileUploadController`.
*/
@interface PFFileUploadResult : NSObject
@property (strong, nonatomic) NSString *url;
@property (strong, nonatomic) NSString *name;
@end
2 changes: 2 additions & 0 deletions Parse/Parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#import <Parse/PFUser+Synchronous.h>
#import <Parse/PFUser+Deprecated.h>
#import <Parse/PFUserAuthenticationDelegate.h>
#import <Parse/PFFileUploadResult.h>
#import <Parse/PFFileUploadController.h>

#if TARGET_OS_IOS

Expand Down
12 changes: 12 additions & 0 deletions Parse/ParseClientConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#import <Parse/PFConstants.h>

@protocol PFFileUploadController;

NS_ASSUME_NONNULL_BEGIN

/**
Expand Down Expand Up @@ -49,6 +51,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy) NSString *server;

/**
Sets a custom file upload controller that uploads PFFiles using its own policy.
*/
@property (nonatomic, strong, readwrite, nullable) id<PFFileUploadController> fileUploadController;

///--------------------------------------
#pragma mark - Enabling Local Datastore
///--------------------------------------
Expand Down Expand Up @@ -120,6 +127,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy, readonly) NSString *server;

/**
The custom upload controller that synchronously uploads PFFiles using its own policy.
*/
@property (nonatomic, strong, readonly, nullable) id<PFFileUploadController> fileUploadController;

///--------------------------------------
#pragma mark - Enabling Local Datastore
///--------------------------------------
Expand Down
2 changes: 2 additions & 0 deletions Parse/ParseClientConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ - (BOOL)isEqual:(id)object {
return ([PFObjectUtilities isObject:self.applicationId equalToObject:other.applicationId] &&
[PFObjectUtilities isObject:self.clientKey equalToObject:other.clientKey] &&
[self.server isEqualToString:other.server] &&
self.fileUploadController == other.fileUploadController &&
self.localDatastoreEnabled == other.localDatastoreEnabled &&
[PFObjectUtilities isObject:self.applicationGroupIdentifier equalToObject:other.applicationGroupIdentifier] &&
[PFObjectUtilities isObject:self.containingApplicationBundleIdentifier equalToObject:other.containingApplicationBundleIdentifier] &&
Expand All @@ -128,6 +129,7 @@ - (instancetype)copyWithZone:(NSZone *)zone {
configuration->_applicationId = [self->_applicationId copy];
configuration->_clientKey = [self->_clientKey copy];
configuration->_server = [self.server copy];
configuration->_fileUploadController = self->_fileUploadController;
configuration->_localDatastoreEnabled = self->_localDatastoreEnabled;
configuration->_applicationGroupIdentifier = [self->_applicationGroupIdentifier copy];
configuration->_containingApplicationBundleIdentifier = [self->_containingApplicationBundleIdentifier copy];
Expand Down

0 comments on commit 2e21ca6

Please sign in to comment.