From eeed76e48c830fe742eadd435682f3b1e6036f83 Mon Sep 17 00:00:00 2001 From: Dmitry Isaikin Date: Mon, 6 Jun 2016 04:28:53 +0400 Subject: Add possibility of fetching message attachment by chunks and store it to file. (#1438) --- src/objc/imap/MCOIMAP.h | 1 + src/objc/imap/MCOIMAPFetchContentToFileOperation.h | 51 ++++++++++ .../imap/MCOIMAPFetchContentToFileOperation.mm | 103 +++++++++++++++++++++ src/objc/imap/MCOIMAPSession.h | 32 +++++++ src/objc/imap/MCOIMAPSession.mm | 16 ++++ 5 files changed, 203 insertions(+) create mode 100644 src/objc/imap/MCOIMAPFetchContentToFileOperation.h create mode 100644 src/objc/imap/MCOIMAPFetchContentToFileOperation.mm (limited to 'src/objc') diff --git a/src/objc/imap/MCOIMAP.h b/src/objc/imap/MCOIMAP.h index 11cbc2ae..4de8f18e 100644 --- a/src/objc/imap/MCOIMAP.h +++ b/src/objc/imap/MCOIMAP.h @@ -30,6 +30,7 @@ #import #import #import +#import #import #import #import diff --git a/src/objc/imap/MCOIMAPFetchContentToFileOperation.h b/src/objc/imap/MCOIMAPFetchContentToFileOperation.h new file mode 100644 index 00000000..4d06e94d --- /dev/null +++ b/src/objc/imap/MCOIMAPFetchContentToFileOperation.h @@ -0,0 +1,51 @@ +// +// MCOIMAPFetchContentToFileOperation.h +// mailcore2 +// +// Created by Dmitry Isaikin on 2/08/16. +// Copyright (c) 2016 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFETCHCONTENTTOFILEOPERATION_H + +#define MAILCORE_MCOIMAPFETCHCONTENTTOFILEOPERATION_H + +/** + This class implements an operation to fetch the content of a message to the file. + It can be a part or a full message. +*/ + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface MCOIMAPFetchContentToFileOperation : MCOIMAPBaseOperation + +/** + This block will be called as bytes are received from the network +*/ +@property (nonatomic, copy, nullable) MCOIMAPBaseOperationProgressBlock progress; + +@property (nonatomic, assign, getter=isLoadingByChunksEnabled) BOOL loadingByChunksEnabled; +@property (nonatomic, assign) uint32_t chunksSize; +@property (nonatomic, assign) uint32_t estimatedSize; + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h` +*/ + +- (void) start:(void (^)(NSError * __nullable error))completionBlock; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/src/objc/imap/MCOIMAPFetchContentToFileOperation.mm b/src/objc/imap/MCOIMAPFetchContentToFileOperation.mm new file mode 100644 index 00000000..4f2bbfcf --- /dev/null +++ b/src/objc/imap/MCOIMAPFetchContentToFileOperation.mm @@ -0,0 +1,103 @@ +// +// MCOIMAPFetchContentToFileOperation.mm +// mailcore2 +// +// Created by Dmitry Isaikin on 2/08/16. +// Copyright (c) 2016 MailCore. All rights reserved. +// + +#import "MCOIMAPFetchContentToFileOperation.h" + +#include "MCAsyncIMAP.h" + +#import "MCOOperation+Private.h" +#import "MCOUtils.h" + +typedef void (^CompletionType)(NSError *error); + +@implementation MCOIMAPFetchContentToFileOperation { + CompletionType _completionBlock; + MCOIMAPBaseOperationProgressBlock _progress; +} + +@synthesize progress = _progress; + +#define nativeType mailcore::IMAPFetchContentToFileOperation + ++ (void) load +{ + MCORegisterClass(self, &typeid(nativeType)); +} + ++ (NSObject *) mco_objectWithMCObject:(mailcore::Object *)object +{ + nativeType * op = (nativeType *) object; + return [[[self alloc] initWithMCOperation:op] autorelease]; +} + +- (void)setLoadingByChunksEnabled:(BOOL)loadingByChunksEnabled { + MCO_NATIVE_INSTANCE->setLoadingByChunksEnabled(loadingByChunksEnabled); +} + +- (BOOL)isLoadingByChunksEnabled { + return MCO_NATIVE_INSTANCE->isLoadingByChunksEnabled(); +} + +- (void)setChunksSize:(uint32_t)chunksSize { + MCO_NATIVE_INSTANCE->setChunksSize(chunksSize); +} + +- (uint32_t)chunksSize { + return MCO_NATIVE_INSTANCE->chunksSize(); +} + +- (void)setEstimatedSize:(uint32_t)estimatedSize { + MCO_NATIVE_INSTANCE->setEstimatedSize(estimatedSize); +} + +- (uint32_t)estimatedSize { + return MCO_NATIVE_INSTANCE->estimatedSize(); +} + +- (void) dealloc +{ + [_progress release]; + [_completionBlock release]; + [super dealloc]; +} + +- (void) start:(void (^)(NSError *error))completionBlock { + _completionBlock = [completionBlock copy]; + [self start]; +} + +- (void) cancel +{ + [_completionBlock release]; + _completionBlock = nil; + [super cancel]; +} + +- (void) operationCompleted +{ + if (_completionBlock == NULL) + return; + + nativeType *op = MCO_NATIVE_INSTANCE; + if (op->error() == mailcore::ErrorNone) { + _completionBlock(nil); + } else { + _completionBlock([NSError mco_errorWithErrorCode:op->error()]); + } + [_completionBlock release]; + _completionBlock = nil; +} + +- (void) bodyProgress:(unsigned int)current maximum:(unsigned int)maximum +{ + if (_progress != NULL) { + _progress(current, maximum); + } +} + +@end diff --git a/src/objc/imap/MCOIMAPSession.h b/src/objc/imap/MCOIMAPSession.h index 7674e9db..12a1e651 100644 --- a/src/objc/imap/MCOIMAPSession.h +++ b/src/objc/imap/MCOIMAPSession.h @@ -24,6 +24,7 @@ @class MCOIndexSet; @class MCOIMAPFetchMessagesOperation; @class MCOIMAPFetchContentOperation; +@class MCOIMAPFetchContentToFileOperation; @class MCOIMAPFetchParsedContentOperation; @class MCOIMAPSearchOperation; @class MCOIMAPIdleOperation; @@ -848,6 +849,37 @@ vanishedMessages will be set only for servers that support QRESYNC. See [RFC5162 partID:(NSString *)partID encoding:(MCOEncoding)encoding; +/** + Returns an operation to fetch an attachment to a file. + @param urgent is set to YES, an additional connection to the same folder might be opened to fetch the content. + Operation will be perform in a memory efficient manner. + + MCOIMAPFetchContentToFileOperation * op = [session fetchMessageAttachmentToFileOperationWithFolder:@"INBOX" + uid:456 + partID:@"1.2" + encoding:MCOEncodingBase64 + filename:filename + urgent:YES]; + + // Optionally, explicitly enable chunked mode + [op setLoadingByChunksEnabled:YES]; + [op setChunksSize:1024*1024]; + // need in chunked mode for correct progress indication + [op setEstimatedSize:sizeOfAttachFromBodystructure]; + + [op start:^(NSError * __nullable error) { + ... + }]; + + */ +- (MCOIMAPFetchContentToFileOperation *) fetchMessageAttachmentToFileOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid + partID:(NSString *)partID + encoding:(MCOEncoding)encoding + filename:(NSString *)filename + urgent:(BOOL)urgent; + + /** @name General IMAP Actions */ /** diff --git a/src/objc/imap/MCOIMAPSession.mm b/src/objc/imap/MCOIMAPSession.mm index 2eba5cc0..94a3020b 100644 --- a/src/objc/imap/MCOIMAPSession.mm +++ b/src/objc/imap/MCOIMAPSession.mm @@ -498,6 +498,22 @@ MCO_OBJC_SYNTHESIZE_SCALAR(dispatch_queue_t, dispatch_queue_t, setDispatchQueue, return [self fetchMessageAttachmentOperationWithFolder:folder number:number partID:partID encoding:encoding urgent:NO]; } +- (MCOIMAPFetchContentToFileOperation *) fetchMessageAttachmentToFileOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid + partID:(NSString *)partID + encoding:(MCOEncoding)encoding + filename:(NSString *)filename + urgent:(BOOL)urgent +{ + IMAPFetchContentToFileOperation * coreOp = MCO_NATIVE_INSTANCE->fetchMessageAttachmentToFileByUIDOperation([folder mco_mcString], + uid, + [partID mco_mcString], + (Encoding) encoding, + [filename mco_mcString], + urgent); + return MCO_TO_OBJC_OP(coreOp); +} + - (MCOIMAPOperation *) storeFlagsOperationWithFolder:(NSString *)folder uids:(MCOIndexSet *)uids kind:(MCOIMAPStoreFlagsRequestKind)kind -- cgit v1.2.3