本文介绍了将文件上载到OneDrive。 401错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 BITS 协议将大文件上传到 OneDrive 。这是

I'm implementing uploading big files to OneDrive by using BITS protocol. Here is the documentation

我'我有以下问题。在我尝试创建会话后登录一段时间后,我收到401错误。以下是完整的回复:

I'm having the following issue. After a certain period of time of being logged in when I'm trying to create a session I'm receiving 401 error. Here's the complete response:

<NSHTTPURLResponse: 0x7d6ee0f0> { URL: https://cid-da1cedf5484811a9.users.storage.live.com/items/DA1CEDF5484811A9!373/IMG_0003.JPG } { status code: 401, headers {
"BITS-Packet-Type" = Ack;
"Content-Length" = 0;
Date = "Mon, 22 Dec 2014 09:50:22 GMT";
P3P = "CP=\"BUS CUR CONo FIN IVDo ONL OUR PHY SAMo TELo\"";
Server = "Microsoft-HTTPAPI/2.0";
"X-AsmVersion" = "UNKNOWN; 19.9.0.0";
"X-ClientErrorCode" = AccessDenied;
"X-MSNSERVER" = "SN3301____PAP101";
"X-QosStats" = "{\"ApiId\":0,\"ResultType\":2,\"SourcePropertyId\":0,\"TargetPropertyId\":42}";
"X-ThrowSite" = "4e1b.c093";
} }

这是我的请求的样子:

{
Authorization = "EwCAAq1DBAAUGCCXc8wU/zFu9QnLdZXy+YnElFkAAYejThC8LqFmGJx4sT4Wv11wzA6Cj9tleMQ+PM4PGXSV/DAorkfRiVnt+KQnZRI90XL/FIfwTvhWmp6jFhsppM39GgwbQ7it0tSVCSp4cIFCFSphmV783o+MKPeuEsw79mRGL5Kz2lcrVUxQAq12vUZXnhkX4qiJj0RqMSdaFYghfVVmhkcGsJITOwIisFq/JyaRoffgcW7vZCu9/9Q1Jm62f+bcGur82sTo5ucwV4M7QNtl77nVjv3tPElcUDgZnTvCLuhIE6QHY6yHS+9blWVbaXJBBD0ZPjDbUdjIlbexto6VvXtjp+vELL8rMSJMYcGjN4AxbGmBDnjLm9Iy1RIDZgAACALsAIEvRqDnUAFmIs8toBlRzfxctJcm1wxfqY/531QSDMVG9pIISpNCPppHAa/blSV8+LbLO/hW5i/36/3RTLpFAiXkPxzbkI8OJSrVRDfKcXiK1x+kTNFtcxXLBlJSWYlMY9OcwT+v/JTQnoGD1z6L56zOX53Gt7SBZQ0of7e3QecxHLX7w9lqs0jBmRvwL9I/n0+r9r6CI3tTEnFODFyED9ToBCRwwjLLD8P4qWRXWC1BUL+20v2QCQYRKzSDxZkYa3WrPLA4PIEFdFp58/limBzDrGW4MaWi1UgaI/QF8gN5n+JLNE4YcZL8KaXFZ76zNWNhJFsg4Lctsu95l7oD9MkezDvpA8bhkoNp39rEvPjBEurrFkdHviv73Z/C1W+IoA4ww3ZAYtIt3THtvPE4wq2fUEcb+MhOIG7abZtu4P07+5Zy2UO1rGlChE/pvmtV4XXrrg3TLG5zAQ==";
"BITS-Packet-Type" = "Create-Session";
"BITS-Supported-Protocols" = "{7df0354d-249b-430f-820d-3d2a9bef4931}";
"X-Http-Method-Override" = "BITS_POST";
}

如果需要,我可以发布用于打开会话的代码,我不会现在发布,因为它非常大。

I can post code used to open session if you need, I don't post it now because it's pretty large.

好的,我想到的第一件事就是访问令牌已经过时了,我需要以某种方式更新它。但!就在我使用相同的访问令牌执行检索用户ID的请求之前:

OK, the first thing that comes to my mind is that access token has got outdated and I need to renew it somehow. BUT! Just before I perform request to retrieve user Id using the same access token:

- (void)retrieveUserId
{
NSString                  *urlString            = [NSString stringWithFormat:@"https://apis.live.net/v5.0/me?access_token=%@", commonAccessToken];
NSURL                     *url                  = [NSURL URLWithString:urlString];
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession              *session              = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSURLSessionDataTask      *task                 = [session dataTaskWithURL:url
                                                         completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){

                                                             NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;

                                                             if (httpResponse.statusCode == 200)
                                                             {
                                                                 NSLog(@"Response retrieving user id %@", httpResponse);

                                                                 NSError      *parsingError     = nil;
                                                                 NSDictionary *parsedDictionary = [NSJSONSerialization JSONObjectWithData:data
                                                                                                                                  options:kNilOptions
                                                                                                                                    error:&parsingError];
                                                                 if (!parsingError)
                                                                 {
                                                                     commonUserId = parsedDictionary[@"id"];
                                                                     [self createUploadRequest];
                                                                 }
                                                                 else
                                                                 {
                                                                     dispatch_async(dispatch_get_main_queue(), ^{

                                                                         [self.delegate bitsClient:self didFailWithError:parsingError];

                                                                     });
                                                                 }
                                                             }
                                                             else
                                                             {
                                                                 dispatch_async(dispatch_get_main_queue(), ^{

                                                                     [self.delegate bitsClient:self didFailWithError:error];

                                                                 });
                                                             }
                                                         }];
[task resume];
}

它有效。当我获得用户ID时,此访问令牌是正常的。但是你可以看到,与尝试打开会话时不同,访问令牌是作为url的一部分而不是作为头字段之一。我不确定它是否重要。到现在为止我无法解释这种行为。如果我退出并再次登录,那么它再次正常,我不再收到401错误,所以我真的应该更新令牌,但是怎么办呢?还有一件事让你知道 - 当我从 LiveConnectSession 获得访问令牌时,我会检查这个会话是否过期而不是。其到期属性晚于 [NSDate date]

And it works. This access token is OK when I get the user Id. But you can see that here unlike when trying to open a session the access token is put as a part of url, not as one of header fields. I'm not sure if it matters or not. By now I can't explain such a behaviour. If I logout and login again then it's OK again, I don't receive the 401 error anymore, so probably I really should renew the token, but how can it be done? One more thing for you to know - when I get the access token from LiveConnectSession I check if this session is expired and it's not. Its expires property is later than [NSDate date].

还有一件事让你知道 - 尽管我无法打开会话,如果我尝试使用上传文件,我的请求被401错误拒绝 Live SDK LiveOperation 文件上传时没有任何错误。

Also one more thing for you to know - despite I'm not able to open session and my request is being rejected with 401 error if I try to upload files by using Live SDK's LiveOperation the files are uploaded without any error.

我想恢复:经过一段时间(似乎是24小时但我不确定)以 OneDrive身份登录用户我无法使用 BITS 协议上传文件,因为我收到401错误。同时会话似乎没有过期,我仍然可以使用 LiveOperation 上传文件。此外,我可以使用打开上传会话时使用的相同访问令牌轻松获取用户ID。如果我退出并再次登录,那么一切都像魅力一样,我可以创建会话和上传文件。

I want to resume: After a certain period (seems like it is 24 hours but I'm not sure) of being logged in as OneDrive user I become unable to upload files using BITS protocol because I receive 401 error. At the same time the session seems to be not expired and I can still upload files by using LiveOperation. Also I can easily get user id using the same access token which is used when opening an upload session. If I logout and login again then again everything works like charm and I'm able to create session and upload files.

似乎这就是我可以告诉你的全部内容,但如果您需要任何其他信息,请告诉我。任何帮助都非常感谢。

Seems like this is all that I can tell you, but if you need any additional info please tell me. Any help is extremely appreciated.

推荐答案

安德烈,我是php开发人员,这是我在php中所做的:

Andrey, i am php developer and here is what i am doing in php:

const API_URL = 'https://apis.live.net/v5.0/';
const INITAPIURL = 'https://login.live.com/oauth20_token.srf';
const URI_AUTHORIZE = 'https://login.live.com/oauth20_authorize.srf';

1)获取访问令牌并保存刷新令牌(下面的函数生成URL以重定向用户oAuth)

1) getting access token and saving refresh token (function below generate URL to redirect user for oAuth)

public function getAuthorizeUrl($cburl) {
        $cburl=_SKYDRIVE_REDIRECT_URI;
        return self::URI_AUTHORIZE.'?client_id='.urlencode(_SKYDRIVE_API_CLIENT_ID).'&scope='.urlencode('wl.offline_access wl.skydrive wl.skydrive_update wl.emails wl.contacts_skydrive wl.contacts_photos').'&response_type=code&redirect_uri='.urlencode($cburl);
    }

2)每隔3300秒(访问令牌直播3600秒)我刷新直接在服务器上使用刷新令牌访问令牌(在浏览器中没有用户确认)

2) after every 3300 seconds (access token live for 3600 sec) i refresh access token with refresh token directly on server (without user confirmation in browser)

$r = $this->http(self::INITAPIURL, 'POST', array("grant_type" => "refresh_token", "client_id" => _SKYDRIVE_API_CLIENT_ID, "client_secret" => _SKYDRIVE_API_SECRET, "redirect_uri" => _SKYDRIVE_REDIRECT_URI, "refresh_token" => $this->refreshtoken));

3)我发送访问令牌作为带有curl的标头,用于我对API的所有请求(令牌刷新除外)上面)

3) i am sending access token as header with curl for all my requests to API (except token refresh above)

$headers[] = "Authorization: Bearer " . $this->token;

以上步骤在我使用BITS时工作(我刚刚在perl上实现了BITS协议使用,一切都是工作)

and above steps are working when i use BITS (i just implemented BITS protocol use on perl and everything is working)

PS谢谢你发了ID文件夹的URL,他们在文档中有错误的URL:)

P.S. Thank you that you posted URL of folder by ID they had wrong URL in documentation :)

这篇关于将文件上载到OneDrive。 401错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 19:54
查看更多