NSURLSession确保上传工作 [英] NSURLSession make sure Upload worked

查看:106
本文介绍了NSURLSession确保上传工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

确保上传有效的最佳方法是什么?

What's the best approach to make sure that an upload works?

我需要将图片上传到服务器并确保上传工作正常。如果由于某种原因上传不起作用,我将不得不稍后重试。

I need to upload images, to a server and make sure, that the upload has worked. If, for whatever reason, the upload did not work, I'll have to retry later.

目前,我正在使用NSUrlSession上传图片:

Currently, I'm using NSUrlSession to upload the image:

- (void)didCreateSignature:(UIImage *)image {

    BLog();

    NSArray   *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString  *documentsDirectory = [paths objectAtIndex:0];
    NSString  *imageFile = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"test.png"];


    NSData *imageData = UIImagePNGRepresentation(image);
    [imageData writeToFile:imageFile atomically:YES];

    while (![[NSFileManager defaultManager] fileExistsAtPath:imageFile]) {
        [NSThread sleepForTimeInterval:.5];
    }


    NSURLSession *session = [self backgroundSession];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:self.uploadUrl]];
    [request setHTTPMethod:@"POST"];
    [request addValue:@"image/png" forHTTPHeaderField:@"Content-Type"];

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:signatureFile]];

    [uploadTask resume];

}

现在让我们假设用户没有互联网连接,然后代理人将被解雇:

Now let's assume that the user does not have internet connection, then the delegate will be fired:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();

    if (error == nil)
    {
        NSLog(@"Task: %@ completed successfully", task);
    }
    else
    {
        NSLog(@"Task: %@ completed with error: %@", [task originalRequest], [error localizedDescription]);


        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:) name:kReachabilityChangedNotification object:nil];
            self.internetReachability = [Reachability reachabilityForInternetConnection];
            [self.internetReachability startNotifier];
        });


    }

}

根据Apple文档,如果Reachability状态已更改,您应稍后重试。所以我想把这些任务添加到一个数组,并在互联网连接可用后再次启动每个任务。

According to the Apple Documentation you should retry later if the Reachability status has changed. So i was thinking of adding these tasks to an Array and start each task again once the Internet connection has become available.

这是正确的方法吗?

如果用户关闭应用程序(通过TaskManager)会发生什么。我怎样才能确保这些任务能够恢复?

And what happens, if the user closes the app (via TaskManager). How can I make sure that these tasks will be resumed ?

推荐答案

与此同时,我使用自定义的UploadManager类解决了这个问题并在Core Data中存储下载,直到上传成功:(以下代码不完整,只显示基本概念。如果有人对完整实施感兴趣,请告诉我)

In the meantime, I solved it by using a custom UploadManager Class and store downloads in Core Data until the upload was successful: (Below Code is not complete, and only shows the basic concept. If anybody is interested in the full implementation, please let me know)

@implementation UploadManager

- (void) uploadImage:(UIImage *)image toUrl:(NSString *)uploadUrl insertIntoDB:(BOOL)insertIntoDB

{
    if(insertIntoDB) {
        [self insertUploadTaskIntoDBWithImage:image andUploadUrl:uploadUrl];
    }


    // Background upload only works with files
    NSString *fileName = [NSString stringWithFormat:@"%@%@", [uploadUrl sha256], @".png"];
    NSString *signatureFile = [NSString stringWithFormat:@"%@/%@",  NSTemporaryDirectory(), fileName];

    NSData *imageData = UIImagePNGRepresentation(image);
    [imageData writeToFile:signatureFile atomically:YES];

    while (![[NSFileManager defaultManager] fileExistsAtPath:signatureFile]) {
        [NSThread sleepForTimeInterval:.5];
    }

    NSURLSession *session = [self backgroundSession];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:uploadUrl]];
    [request setHTTPMethod:@"POST"];
    [request addValue:@"image/png" forHTTPHeaderField:@"Content-Type"];

    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:[NSURL fileURLWithPath:signatureFile]];

    [self showNetworkActivity:YES];

    self.taskCount++;
    [uploadTask resume];
}


-(void) uploadTasksInDatabase
{
    NSArray* uploadTasks = [self getAllUploadTasksFromDatabase];

    for(UploadTask *task in uploadTasks) {
        UIImage *image = [UIImage imageWithData:task.signature];
        [self uploadImage:image toUrl:task.uploadUrl insertIntoDB:NO];
    }
}


/*
 If an application has received an 
 application:handleEventsForBackgroundURLSession:completionHandler: message, the session
 delegate will receive this message to indicate that all messages previously enqueued for this
 session have been delivered. At this time it is safe to invoke the previously stored completion
 handler, or to begin any internal updates that will result in invoking the completion handler.
 */
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    if (appDelegate.backgroundSessionCompletionHandler) {
        void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
        appDelegate.backgroundSessionCompletionHandler = nil;
        completionHandler();
    }

    self.taskCount = 0;
    NSDebug(@"All tasks are finished");

    [self clearDatabase];

}



- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();


    self.taskCount--;
    [[NSNotificationCenter defaultCenter] postNotificationName:[task.originalRequest.URL description] object:self];

    if(self.taskCount == 0) {
        [self showNetworkActivity:NO];
    }


    if (error == nil)
    {
        NSLog(@"Task: %@ completed successfully", [task.originalRequest.URL description]);
        [self deleteUploadTaskWithUploadUrl:[task.originalRequest.URL description]];
    }
    else
    {
        NSLog(@"Task: %@ completed with error: %@", [task.originalRequest.URL description], [error localizedDescription]);

    }

}

在应用程序中委托插入以下内容:

In the App delegate insert the following:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Try to reupload all tasks in DB
    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(backgroundQueue, ^{
            [self.uploadManager uploadTasksInDatabase];
    });


    return YES;
}

这样,只要应用程序再次启动,它就会尝试重新上载所有未完成的任务。

This way it will try to reupload all unfinished tasks whenever the application is started again.

这篇关于NSURLSession确保上传工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆