public Task DeleteAsync(FileState state, string sessionToken, CancellationToken cancellationToken) { var command = new AVCommand("files/" + state.ObjectId, method: "DELETE", sessionToken: sessionToken, data: null); return commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken); }
internal void MergeFromJSON(FileState state, IDictionary <string, object> jsonData) { lock (this.mutex) { string url = jsonData["url"] as string; state.Url = new Uri(url, UriKind.Absolute); state.bucketId = FetchBucketId(url); state.token = jsonData["token"] as string; state.bucket = jsonData["bucket"] as string; state.ObjectId = jsonData["objectId"] as string; } }
public virtual Task<FileState> SaveAsync(FileState state, Stream dataStream, String sessionToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken = default(CancellationToken)) { if (state.Url != null) { // !isDirty return Task<FileState>.FromResult(state); } if (cancellationToken.IsCancellationRequested) { var tcs = new TaskCompletionSource<FileState>(); tcs.TrySetCanceled(); return tcs.Task; } var oldPosition = dataStream.Position; var command = new AVCommand("files/" + state.Name, method: "POST", sessionToken: sessionToken, contentType: state.MimeType, stream: dataStream); return commandRunner.RunCommandAsync(command, uploadProgress: progress, cancellationToken: cancellationToken).OnSuccess(uploadTask => { var result = uploadTask.Result; var jsonData = result.Item2; cancellationToken.ThrowIfCancellationRequested(); return new FileState { Name = jsonData["name"] as string, Url = new Uri(jsonData["url"] as string, UriKind.Absolute), MimeType = state.MimeType }; }).ContinueWith(t => { // Rewind the stream on failure or cancellation (if possible) if ((t.IsFaulted || t.IsCanceled) && dataStream.CanSeek) { dataStream.Seek(oldPosition, SeekOrigin.Begin); } return t; }).Unwrap(); }
public virtual Task <FileState> SaveAsync(FileState state, Stream dataStream, String sessionToken, IProgress <AVUploadProgressEventArgs> progress, CancellationToken cancellationToken = default(CancellationToken)) { if (state.Url != null) { // !isDirty return(Task <FileState> .FromResult(state)); } if (cancellationToken.IsCancellationRequested) { var tcs = new TaskCompletionSource <FileState>(); tcs.TrySetCanceled(); return(tcs.Task); } var oldPosition = dataStream.Position; var command = new AVCommand("files/" + state.Name, method: "POST", sessionToken: sessionToken, contentType: state.MimeType, stream: dataStream); return(commandRunner.RunCommandAsync(command, uploadProgress: progress, cancellationToken: cancellationToken).OnSuccess(uploadTask => { var result = uploadTask.Result; var jsonData = result.Item2; cancellationToken.ThrowIfCancellationRequested(); return new FileState { Name = jsonData["name"] as string, Url = new Uri(jsonData["url"] as string, UriKind.Absolute), MimeType = state.MimeType }; }).ContinueWith(t => { // Rewind the stream on failure or cancellation (if possible) if ((t.IsFaulted || t.IsCanceled) && dataStream.CanSeek) { dataStream.Seek(oldPosition, SeekOrigin.Begin); } return t; }).Unwrap()); }
internal Task <Tuple <HttpStatusCode, string> > QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken) { StringBuilder urlBuilder = new StringBuilder(); urlBuilder.AppendFormat("{0}/mkfile/{1}", UP_HOST, fsize); if (key != null) { urlBuilder.AppendFormat("/key/{0}", ToBase64URLSafe(key)); } var metaData = GetMetaData(state, dataStream); StringBuilder sb = new StringBuilder(); foreach (string _key in metaData.Keys) { sb.AppendFormat("/{0}/{1}", _key, ToBase64URLSafe(metaData[_key].ToString())); } urlBuilder.Append(sb.ToString()); IList <KeyValuePair <string, string> > headers = new List <KeyValuePair <string, string> >(); //makeBlockDic.Add("Content-Type", "application/octet-stream"); string authHead = "UpToken " + upToken; headers.Add(new KeyValuePair <string, string>("Authorization", authHead)); int proCount = ctxes.Length; Stream body = new MemoryStream(); for (int i = 0; i < proCount; i++) { byte[] bctx = StringToAscii(ctxes[i]); body.Write(bctx, 0, bctx.Length); if (i != proCount - 1) { body.WriteByte((byte)','); } } body.Seek(0, SeekOrigin.Begin); var rtn = AVClient.RequestAsync(new Uri(urlBuilder.ToString()), "POST", headers, body, "text/plain", cancellationToken).OnSuccess(_ => { var dic = AVClient.ReponseResolve(_.Result, CancellationToken.None); return(_.Result); }); return(rtn); }
public override Task <FileState> SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress <AVUploadProgressEventArgs> progress, CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { if (state.Url != null) { return(Task.FromResult(state)); } return(GetFileToken(state, cancellationToken).OnSuccess(t => { var fileToken = t.Result.Item2; var uploadUrl = fileToken["upload_url"].ToString(); state.ObjectId = fileToken["objectId"].ToString(); string url = fileToken["url"] as string; state.Url = new Uri(url, UriKind.Absolute); return PutFile(state, uploadUrl, dataStream); }).Unwrap().OnSuccess(s => { return s.Result; })); }
public override Task <FileState> SaveAsync(FileState state, Stream dataStream, String sessionToken, IProgress <AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) { if (state.Url != null) { return(Task <FileState> .FromResult(state)); } state.frozenData = dataStream; state.CloudName = GetUniqueName(state); return(GetQiniuToken(state, CancellationToken.None).ContinueWith(t => { MergeFromJSON(state, t.Result.Item2); return UploadNextChunk(state, dataStream, string.Empty, 0, progress); }).Unwrap().OnSuccess <FileState>(s => { return state; })); }
public Task <FileState> SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress <AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) { if (state.Url != null) { return(Task <FileState> .FromResult(state)); } fileState = state; data = dataStream; return(GetFileToken(fileState, cancellationToken).OnSuccess(_ => { var fileToken = _.Result.Item2; uploadUrl = fileToken["upload_url"].ToString(); token = fileToken["token"].ToString(); fileState.ObjectId = fileToken["objectId"].ToString(); bucket = fileToken["bucket"].ToString(); return FileSlice(cancellationToken).OnSuccess(t => { if (done) { return Task <FileState> .FromResult(state); } var response = t.Result.Item2; var resumeData = response["data"] as IDictionary <string, object>; if (resumeData.ContainsKey("access_url")) { return Task <FileState> .FromResult(state); } var sliceSession = resumeData["session"].ToString(); var sliceOffset = long.Parse(resumeData["offset"].ToString()); return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken); }).Unwrap(); }).Unwrap()); }
internal IDictionary <string, object> GetMetaData(FileState state, Stream data) { IDictionary <string, object> rtn = new Dictionary <string, object>(); if (state.MetaData != null) { foreach (var meta in state.MetaData) { rtn.Add(meta.Key, meta.Value); } } MergeDic(rtn, "mime_type", AVFile.GetMIMEType(state.Name)); MergeDic(rtn, "size", data.Length); MergeDic(rtn, "_checksum", GetMD5Code(data)); if (AVUser.CurrentUser != null) { if (AVUser.CurrentUser.ObjectId != null) { MergeDic(rtn, "owner", AVUser.CurrentUser.ObjectId); } } return(rtn); }
IList<KeyValuePair<string, string>> GetQiniuRequestHeaders(FileState state) { IList<KeyValuePair<string, string>> makeBlockHeaders = new List<KeyValuePair<string, string>>(); string authHead = "UpToken " + state.token; makeBlockHeaders.Add(new KeyValuePair<string, string>("Authorization", authHead)); return makeBlockHeaders; }
internal Task<Tuple<HttpStatusCode, string>> QiniuMakeFile(FileState state, Stream dataStream, string upToken, string key, long fsize, string[] ctxes, CancellationToken cancellationToken) { StringBuilder urlBuilder = new StringBuilder(); urlBuilder.AppendFormat("{0}/mkfile/{1}", UP_HOST, fsize); if (key != null) { urlBuilder.AppendFormat("/key/{0}", ToBase64URLSafe(key)); } var metaData = GetMetaData(state, dataStream); StringBuilder sb = new StringBuilder(); foreach (string _key in metaData.Keys) { sb.AppendFormat("/{0}/{1}", _key, ToBase64URLSafe(metaData[_key].ToString())); } urlBuilder.Append(sb.ToString()); IList<KeyValuePair<string, string>> headers = new List<KeyValuePair<string, string>>(); //makeBlockDic.Add("Content-Type", "application/octet-stream"); string authHead = "UpToken " + upToken; headers.Add(new KeyValuePair<string, string>("Authorization", authHead)); int proCount = ctxes.Length; Stream body = new MemoryStream(); for (int i = 0; i < proCount; i++) { byte[] bctx = StringToAscii(ctxes[i]); body.Write(bctx, 0, bctx.Length); if (i != proCount - 1) { body.WriteByte((byte)','); } } body.Seek(0, SeekOrigin.Begin); var rtn = AVClient.RequestAsync(new Uri(urlBuilder.ToString()), "POST", headers, body, "text/plain", cancellationToken).OnSuccess(_ => { var dic = AVClient.ReponseResolve(_.Result, CancellationToken.None); return _.Result; }); return rtn; }
internal void MergeFromJSON(FileState state, IDictionary<string, object> jsonData) { lock (this.mutex) { string url = jsonData["url"] as string; state.Url = new Uri(url, UriKind.Absolute); state.bucketId = FetchBucketId(url); state.token = jsonData["token"] as string; state.bucket = jsonData["bucket"] as string; state.ObjectId = jsonData["objectId"] as string; } }
internal string GetUniqueName(FileState state) { string key = Guid.NewGuid().ToString();//file Key in Qiniu. string extension = Path.GetExtension(state.Name); key += extension; return key; }
Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress<AVUploadProgressEventArgs> progress) { var totalSize = dataStream.Length; var remainingSize = totalSize - state.completed; if (progress != null) { lock (mutex) { progress.Report(new AVUploadProgressEventArgs() { Progress = AVFileController.CalcProgress(state.completed, totalSize) }); } } if (state.completed == totalSize) { return QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None); } else if (state.completed % BLOCKSIZE == 0) { var firstChunkBinary = GetChunkBinary(state.completed, dataStream); var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize; return MakeBlock(state, firstChunkBinary, blockSize).ContinueWith(t => { var dic = AVClient.ReponseResolve(t.Result, CancellationToken.None); var ctx = dic.Item2["ctx"].ToString(); offset = long.Parse(dic.Item2["offset"].ToString()); var host = dic.Item2["host"].ToString(); state.completed += firstChunkBinary.Length; if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } return UploadNextChunk(state, dataStream, ctx, offset, progress); }).Unwrap(); } else { var chunkBinary = GetChunkBinary(state.completed, dataStream); return PutChunk(state, chunkBinary, context, offset).ContinueWith(t => { var dic = AVClient.ReponseResolve(t.Result, CancellationToken.None); var ctx = dic.Item2["ctx"].ToString(); offset = long.Parse(dic.Item2["offset"].ToString()); var host = dic.Item2["host"].ToString(); state.completed += chunkBinary.Length; if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } //if (AVClient.fileUploaderDebugLog) //{ // AVClient.LogTracker(state.counter + "|completed=" + state.completed + "stream:position=" + dataStream.Position + "|"); //} return UploadNextChunk(state, dataStream, ctx, offset, progress); }).Unwrap(); } }
public Task<FileState> SaveAsync(FileState state, Stream dataStream, string sessionToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) { if (state.Url != null) { return Task<FileState>.FromResult(state); } fileState = state; data = dataStream; return AVFileController.GetFileToken(fileState, cancellationToken).OnSuccess(_ => { var fileToken = _.Result.Item2; uploadUrl = fileToken["upload_url"].ToString(); token = fileToken["token"].ToString(); fileState.ObjectId = fileToken["objectId"].ToString(); bucket = fileToken["bucket"].ToString(); return FileSlice(cancellationToken).OnSuccess(t => { if (done) return Task<FileState>.FromResult(state); var response = t.Result.Item2; var resumeData = response["data"] as IDictionary<string, object>; if (resumeData.ContainsKey("access_url")) return Task<FileState>.FromResult(state); var sliceSession = resumeData["session"].ToString(); var sliceOffset = long.Parse(resumeData["offset"].ToString()); return UploadSlice(sliceSession, sliceOffset, dataStream, progress, cancellationToken); }).Unwrap(); }).Unwrap(); }
internal static Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetFileToken(FileState fileState, CancellationToken cancellationToken) { Task<Tuple<HttpStatusCode, IDictionary<string, object>>> rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = fileState.Name; IDictionary<string, object> parameters = new Dictionary<string, object>(); parameters.Add("name", str); parameters.Add("key", GetUniqueName(fileState)); parameters.Add("__type", "File"); parameters.Add("mime_type", AVFile.GetMIMEType(str)); parameters.Add("metaData", fileState.MetaData); rtn = AVClient.RequestAsync("POST", new Uri("/fileTokens", UriKind.Relative), currentSessionToken, parameters, cancellationToken); return rtn; }
internal static string GetUniqueName(FileState fileState) { string key = Random(12); string extension = Path.GetExtension(fileState.Name); key += extension; fileState.CloudName = key; return key; }
/// <summary> /// 根据文件名,Uri,文件类型以及文件源信息 /// </summary> /// <param name="name">文件名</param> /// <param name="uri">文件Uri</param> /// <param name="mimeType">文件类型</param> /// <param name="metaData">文件源信息</param> public AVFile(string name, Uri uri, string mimeType = null, IDictionary<string, object> metaData = null) { mimeType = mimeType == null ? GetMIMEType(name) : mimeType; state = new FileState { Name = name, Url = uri, MetaData = metaData }; lock (Mutex) { objectCounter++; state.counter = objectCounter; } this.isExternal = true; }
internal AVFile(FileState filestate) { this.state = filestate; }
/// <summary> /// 通过文件名,数据流,文件类型,文件源信息构建一个 AVFile /// </summary> /// <param name="name">文件名</param> /// <param name="data">数据流</param> /// <param name="mimeType">文件类型</param> /// <param name="metaData">文件源信息</param> public AVFile(string name, Stream data, string mimeType = null, IDictionary<string, object> metaData = null) { mimeType = mimeType == null ? GetMIMEType(name) : mimeType; state = new FileState { Name = name, MimeType = mimeType, MetaData = metaData }; this.dataStream = data; lock (Mutex) { objectCounter++; state.counter = objectCounter; } }
Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress <AVUploadProgressEventArgs> progress) { var totalSize = dataStream.Length; var remainingSize = totalSize - state.completed; if (progress != null) { lock (mutex) { progress.Report(new AVUploadProgressEventArgs() { Progress = AVFileController.CalcProgress(state.completed, totalSize) }); } } if (state.completed == totalSize) { return(QiniuMakeFile(state, state.frozenData, state.token, state.CloudName, totalSize, state.block_ctxes.ToArray(), CancellationToken.None)); } else if (state.completed % BLOCKSIZE == 0) { var firstChunkBinary = GetChunkBinary(state.completed, dataStream); var blockSize = remainingSize > BLOCKSIZE ? BLOCKSIZE : remainingSize; return(MakeBlock(state, firstChunkBinary, blockSize).ContinueWith(t => { var dic = AVClient.ReponseResolve(t.Result, CancellationToken.None); var ctx = dic.Item2["ctx"].ToString(); offset = long.Parse(dic.Item2["offset"].ToString()); var host = dic.Item2["host"].ToString(); state.completed += firstChunkBinary.Length; if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } return UploadNextChunk(state, dataStream, ctx, offset, progress); }).Unwrap()); } else { var chunkBinary = GetChunkBinary(state.completed, dataStream); return(PutChunk(state, chunkBinary, context, offset).ContinueWith(t => { var dic = AVClient.ReponseResolve(t.Result, CancellationToken.None); var ctx = dic.Item2["ctx"].ToString(); offset = long.Parse(dic.Item2["offset"].ToString()); var host = dic.Item2["host"].ToString(); state.completed += chunkBinary.Length; if (state.completed % BLOCKSIZE == 0 || state.completed == totalSize) { state.block_ctxes.Add(ctx); } //if (AVClient.fileUploaderDebugLog) //{ // AVClient.LogTracker(state.counter + "|completed=" + state.completed + "stream:position=" + dataStream.Position + "|"); //} return UploadNextChunk(state, dataStream, ctx, offset, progress); }).Unwrap()); } }
internal Task <Tuple <HttpStatusCode, IDictionary <string, object> > > GetQiniuToken(FileState state, CancellationToken cancellationToken) { Task <Tuple <HttpStatusCode, IDictionary <string, object> > > rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = state.Name; IDictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("name", str); parameters.Add("key", state.CloudName); parameters.Add("__type", "File"); parameters.Add("mime_type", AVFile.GetMIMEType(str)); state.MetaData = GetMetaData(state, state.frozenData); parameters.Add("metaData", state.MetaData); rtn = AVClient.RequestAsync("POST", new Uri("qiniu", UriKind.Relative), currentSessionToken, parameters, cancellationToken); return(rtn); }
Task<Tuple<HttpStatusCode, string>> MakeBlock(FileState state, byte[] firstChunkBinary, long blcokSize = 4194304) { MemoryStream firstChunkData = new MemoryStream(firstChunkBinary, 0, firstChunkBinary.Length); return AVClient.RequestAsync(new Uri(new Uri(UP_HOST) + string.Format("mkblk/{0}", blcokSize)), "POST", GetQiniuRequestHeaders(state), firstChunkData, "application/octet-stream", CancellationToken.None); }
internal static Task <Tuple <HttpStatusCode, IDictionary <string, object> > > GetFileToken(FileState fileState, CancellationToken cancellationToken) { Task <Tuple <HttpStatusCode, IDictionary <string, object> > > rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = fileState.Name; IDictionary <string, object> parameters = new Dictionary <string, object>(); parameters.Add("name", str); parameters.Add("key", GetUniqueName(fileState)); parameters.Add("__type", "File"); parameters.Add("mime_type", AVFile.GetMIMEType(str)); parameters.Add("metaData", fileState.MetaData); rtn = AVClient.RequestAsync("POST", new Uri("fileTokens", UriKind.Relative), currentSessionToken, parameters, cancellationToken); return(rtn); }
Task<Tuple<HttpStatusCode, string>> PutChunk(FileState state, byte[] chunkBinary, string LastChunkctx, long currentChunkOffsetInBlock) { MemoryStream chunkData = new MemoryStream(chunkBinary, 0, chunkBinary.Length); return AVClient.RequestAsync(new Uri(new Uri(UP_HOST) + string.Format("bput/{0}/{1}", LastChunkctx, currentChunkOffsetInBlock)), "POST", GetQiniuRequestHeaders(state), chunkData, "application/octet-stream", CancellationToken.None); }
internal IDictionary<string, object> GetMetaData(FileState state, Stream data) { IDictionary<string, object> rtn = new Dictionary<string, object>(); if (state.MetaData != null) { foreach (var meta in state.MetaData) { rtn.Add(meta.Key, meta.Value); } } MergeDic(rtn, "mime_type", AVFile.GetMIMEType(state.Name)); MergeDic(rtn, "size", data.Length); MergeDic(rtn, "_checksum", GetMD5Code(data)); if (AVUser.CurrentUser != null) if (AVUser.CurrentUser.ObjectId != null) MergeDic(rtn, "owner", AVUser.CurrentUser.ObjectId); return rtn; }
public override Task<FileState> SaveAsync(FileState state, Stream dataStream, String sessionToken, IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) { if (state.Url != null) { return Task<FileState>.FromResult(state); } state.frozenData = dataStream; state.CloudName = GetUniqueName(state); return GetQiniuToken(state, CancellationToken.None).ContinueWith(t => { MergeFromJSON(state, t.Result.Item2); return UploadNextChunk(state, dataStream, string.Empty, 0, progress); }).Unwrap().OnSuccess<FileState>(s => { return state; }); }
internal Task<Tuple<HttpStatusCode, IDictionary<string, object>>> GetQiniuToken(FileState state, CancellationToken cancellationToken) { Task<Tuple<HttpStatusCode, IDictionary<string, object>>> rtn; string currentSessionToken = AVUser.CurrentSessionToken; string str = state.Name; IDictionary<string, object> parameters = new Dictionary<string, object>(); parameters.Add("name", str); parameters.Add("key", state.CloudName); parameters.Add("__type", "File"); parameters.Add("mime_type", AVFile.GetMIMEType(str)); state.MetaData = GetMetaData(state, state.frozenData); parameters.Add("metaData", state.MetaData); rtn = AVClient.RequestAsync("POST", new Uri("/qiniu", UriKind.Relative), currentSessionToken, parameters, cancellationToken); return rtn; }
/// <summary> /// Saves the file to the LeanCloud cloud. /// </summary> /// <param name="progress">The progress callback.</param> /// <param name="cancellationToken">The cancellation token.</param> public Task SaveAsync(IProgress<AVUploadProgressEventArgs> progress, CancellationToken cancellationToken) { return taskQueue.Enqueue( toAwait => FileController.SaveAsync(state, dataStream, AVUser.CurrentSessionToken, progress, cancellationToken), cancellationToken) .OnSuccess(t => { state = t.Result; }); }
Task <Tuple <HttpStatusCode, string> > MakeBlock(FileState state, byte[] firstChunkBinary, long blcokSize = 4194304) { MemoryStream firstChunkData = new MemoryStream(firstChunkBinary, 0, firstChunkBinary.Length); return(AVClient.RequestAsync(new Uri(new Uri(UP_HOST) + string.Format("mkblk/{0}", blcokSize)), "POST", GetQiniuRequestHeaders(state), firstChunkData, "application/octet-stream", CancellationToken.None)); }