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 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 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(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); }
Task UploadNextChunk(FileState state, Stream dataStream, string context, long offset, IProgress <AVUploadProgressEventArgs> progress) { if (AVClient.fileUploaderDebugLog) { AVClient.LogTracker(state.counter + "|completed=" + state.completed + "|total=" + dataStream.Length + "|"); } 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); } //if (AVClient.fileUploaderDebugLog) //{ // AVClient.LogTracker(AVFile.objectCounter + "|completed=" + state.completed + "stream:position=" + dataStream.Position + "|"); //} 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()); } }
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 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); }