/// <summary> /// 将网盘的文件异步转换成秒传数据文件(将产生一个原文件名.symbollink的文件) /// </summary> /// <param name="path">原文件路径</param> /// <param name="callback">回调函数</param> /// <param name="dst_path">保存的文件名</param> /// <param name="state">附加参数</param> public void ConvertToSymbolLinkAsync(string path, ObjectMetaCallback callback = null, string dst_path = null, object state = null) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } ThreadPool.QueueUserWorkItem(delegate { if (_enable_function_trace) { _trace.TraceInfo("BaiduPCS.ConvertToSymbolLinkAsync called: string path=" + path + "ObjectMetaCallback callback=" + callback?.ToString() + ", string dst_path=" + dst_path); } var url = GetLocateDownloadLink(path); if (url.Length == 0) { _trace.TraceWarning("Locate url length is zero"); callback?.Invoke(false, new ObjectMetadata(), state); return; } var ns = new NetStream(); ns.RetryTimes = 3; ns.CookieKey = _auth.CookieIdentifier; try { var buffer = new byte[BUFFER_SIZE]; var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); int rbytes, total = 0; ns.HttpGet(url[0]); var content_length = ns.HTTP_Response.ContentLength; if (content_length < VALIDATE_SIZE) { _trace.TraceWarning("Content_length is too small, exited"); callback?.Invoke(false, new ObjectMetadata(), state); return; } var stream = ns.ResponseStream; do { rbytes = stream.Read(buffer, 0, BUFFER_SIZE); rbytes = (int)Math.Min(VALIDATE_SIZE - total, rbytes); md5.TransformBlock(buffer, 0, rbytes, buffer, 0); total += rbytes; } while (rbytes > 0 && total < VALIDATE_SIZE); md5.TransformFinalBlock(buffer, 0, 0); var slice_md5 = util.Hex(md5.Hash); //从response处获取其他参数 var content_md5 = ns.HTTP_Response.Headers["Content-MD5"]; var content_crc32 = ns.HTTP_Response.Headers["x-bs-meta-crc32"]; uint int_crc32 = uint.Parse(content_crc32); content_crc32 = int_crc32.ToString("X2").ToLower(); if (string.IsNullOrEmpty(content_crc32) || string.IsNullOrEmpty(content_md5)) { _trace.TraceWarning("Empty content_crc32 or content_md5 detected, pls report this status to developer by opening new issue"); callback?.Invoke(false, new ObjectMetadata(), state); } //尝试发送rapid upload请求 var temp_path = "/BaiduCloudSyncCache/temp-rapid-upload-request-" + Guid.NewGuid().ToString(); var rapid_upload_info = RapidUploadRaw(temp_path, (ulong)content_length, content_md5, content_crc32, slice_md5); DeletePath("/BaiduCloudSyncCache"); if (string.IsNullOrEmpty(rapid_upload_info.MD5) || rapid_upload_info.FS_ID == 0) { _trace.TraceWarning("Validate check: post rapid upload failed, operation aborted"); callback?.Invoke(false, new ObjectMetadata(), state); return; } //rapid upload通过,整合成json格式的文件上传到服务器 var json = new JObject(); json.Add("content_length", content_length); json.Add("content_md5", content_md5); json.Add("content_crc32", content_crc32); json.Add("slice_md5", slice_md5); var str_json = JsonConvert.SerializeObject(json); var bytes_json = Encoding.UTF8.GetBytes(str_json); var stream_to_write = new MemoryStream(); stream_to_write.Write(bytes_json, 0, bytes_json.Length); stream_to_write.Seek(0, SeekOrigin.Begin); if (dst_path == null) { dst_path = path + ".symbollink"; } var file_meta = UploadRaw(stream_to_write, (ulong)bytes_json.Length, dst_path); stream_to_write.Close(); callback?.Invoke(true, file_meta, state); } catch (Exception ex) { _trace.TraceError(ex); } finally { ns.Close(); } }); }
/// <summary> /// 将网盘的秒传数据文件异步转成原文件(将产生一个去掉末尾.symbollink的文件) /// </summary> /// <param name="path">原文件路径</param> /// <param name="callback">回调函数</param> /// <param name="dst_path">保存的文件名</param> /// <param name="state">附加参数</param> public void ConvertFromSymbolLinkAsync(string path, ObjectMetaCallback callback = null, string dst_path = null, object state = null) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } ThreadPool.QueueUserWorkItem(delegate { if (_enable_function_trace) { _trace.TraceInfo("BaiduPCS.ConvertFromSymbolLinkAsync called: string path=" + path + ", ObjectMetaCallback callback=" + callback?.ToString() + ", string dst_path=" + dst_path); } var url = GetLocateDownloadLink(path); if (url.Length == 0) { _trace.TraceWarning("Locate url length is zero"); callback?.Invoke(false, new ObjectMetadata(), state); return; } var ns = new NetStream(); ns.RetryTimes = 3; ns.CookieKey = _auth.CookieIdentifier; try { ns.HttpGet(url[0]); var response_json = ns.ReadResponseString(); var json = JsonConvert.DeserializeObject(response_json) as JObject; var content_length = json.Value <ulong>("content_length"); var content_md5 = json.Value <string>("content_md5"); var content_crc32 = json.Value <string>("content_crc32"); var slice_md5 = json.Value <string>("slice_md5"); if (content_length == 0 || string.IsNullOrEmpty(content_md5) || string.IsNullOrEmpty(content_crc32)) { callback?.Invoke(false, new ObjectMetadata(), state); return; } if (dst_path == null) { dst_path = path.EndsWith(".symbollink") ? path.Substring(0, path.Length - 11) : (path + "." + path.Split('.').Last()); } var data = RapidUploadRaw(dst_path, content_length, content_md5, content_crc32, slice_md5); callback?.Invoke(true, data, state); } catch (Exception ex) { _trace.TraceError(ex); callback?.Invoke(false, new ObjectMetadata(), state); } finally { ns.Close(); } }); }