在等待 SDK 实施的同时,我将一个不可恢复的分块上传到 OneDrive
using Microsoft.OneDrive.Sdk;
using Newtonsoft.Json;
using SimpleAuthenticationProvider;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.OneDrive.Sdk
{
public static class Extend
{
public static async Task<Item> UploadChunks(this OneDriveClient client, string folder, string fileName, Stream stream, int chunkSize, LiveToken token)
{
var session = await client.Drive.Root.ItemWithPath(folder + "/" + fileName).CreateSession(new ChunkedUploadSessionDescriptor() { Name = fileName }).Request().PostAsync();
using (OneDriveChunkUpload chunks = new OneDriveChunkUpload(stream, session.UploadUrl, chunkSize, token))
{
return await client.Drive.Items[chunks.Upload().id].Request().GetAsync();
}
}
}
public class LiveToken
{
public string token_type { get; set; }
public int expires_in { get; set; }
public string scope { get; set; }
public string access_token { get; set; }
public string refresh_token { get; set; }
public string user_id { get; set; }
}
public class itemCreated
{
public string id { get; set; }
public string name { get; set; }
public int size { get; set; }
}
class responseChunk
{
public string uploadUrl { get; set; }
public DateTime expirationDateTime { get; set; }
public List<string> nextExpectedRanges { get; set; }
public List<Range> Ranges
{
get
{
List<Range> ret = new List<Range>();
foreach (var r in nextExpectedRanges)
{
string[] parsed = r.Split('-');
Range ra = new Range(parsed[0], parsed[1]);
ret.Add(ra);
}
return ret;
}
}
}
class Range
{
public Range() { }
public Range(string start, string end)
{
Start = int.Parse(start);
if (!string.IsNullOrEmpty(end))
End = int.Parse(end);
}
public int Start { get; set; }
public int? End { get; set; }
}
public class OneDriveChunkUpload : IDisposable
{
Stream source;
string Url;
int ChunkSize;
responseChunk lastResponse;
LiveToken Token;
public itemCreated item = null;
public OneDriveChunkUpload(Stream str, string url, int chunkSize, LiveToken token)
{
Token = token;
source = str;
Url = url;
ChunkSize = chunkSize;
lastResponse = new responseChunk() { nextExpectedRanges = new List<string>() { "0-" + (str.Length -1).ToString() } };
}
public itemCreated Upload()
{
long position = 0;
while (lastResponse != null)
{
Range r = new Range();
r.Start = lastResponse.Ranges[0].Start;
r.End = (int)Math.Min(((lastResponse.Ranges[0].End ?? int.MinValue) + 1) - r.Start, ChunkSize);
r.End += r.Start -1;
byte[] buffer = new byte[r.End.Value - r.Start + 1];
source.Position = r.Start;
//source.Seek(r.Start, SeekOrigin.Begin);
position += source.Read(buffer, 0, buffer.Length);
Put(buffer, r);
}
return item;
}
void Put(byte[] bytes, Range r)
{
WebRequest req = HttpWebRequest.Create(Url);
req.Method = "PUT";
req.Headers.Add(HttpRequestHeader.Authorization, string.Format("bearer {0}", Token.access_token));
req.ContentLength = bytes.Length;
string ContentRange = string.Format("bytes {0}-{1}/{2}", r.Start, r.End.Value, source.Length);
req.Headers.Add(HttpRequestHeader.ContentRange, ContentRange);
Stream requestStream = req.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
HttpWebResponse res = null;
try
{
res = (HttpWebResponse)req.GetResponse();
}
catch (Exception ex)
{
throw ex;
}
string responseBody = null;
using (StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8))
{
responseBody = sr.ReadToEnd();
}
if (res.StatusCode == HttpStatusCode.Accepted)
{
lastResponse = JsonConvert.DeserializeObject<responseChunk>(responseBody);
}
else if (res.StatusCode == HttpStatusCode.Created)
{
lastResponse = null;
item = JsonConvert.DeserializeObject<itemCreated>(responseBody);
}
else
{
throw new Exception("bad format");
}
}
public void Dispose()
{
WebRequest req = HttpWebRequest.Create(Url);
req.Method = "DELETE";
WebResponse res = req.GetResponse();
}
}
}