using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Runtime.Serialization; using System.Text; using Newtonsoft.Json; using System.Text.RegularExpressions; using System.IO; using System.Web; namespace NetDisk { public static class Operation { /// /// 块完成事件(顺序提交) /// /// 文件名 /// 当前完成的块 /// 总块数 public delegate void ComplateUploadBlockHandle(string filePath, int endBlockNum, int totalBlockNum); public static event ComplateUploadBlockHandle ComplateUploadBlock; /// /// 块失败事件 /// /// /// /// public delegate void FailedUploadBlockHandle(string filePath, int failedBlockNum, int totalBlockNum); public static event FailedUploadBlockHandle FailedUploadBlock; /// /// 初始化上传 /// /// 文件名 /// 文件所拥有的块数 /// 服务器需要上传的块数 public delegate void InitUploadFileHandle(string filePath, int fileBlockNum, int needUploadBlockNum); public static event InitUploadFileHandle InitUploadFile; /// /// 开始上传块 /// /// 文件名 /// 当前开始的块 /// 总块数 public delegate void StartUploadBlockHandle(string filePath, int startBlockNum, int totalBlockNum); public static event StartUploadBlockHandle StartUploadBlock; /// /// 上传完成 /// /// 文件名 public delegate void UpdateComplateHandle(string filePath); public static event UpdateComplateHandle UpdateComplate; /// /// 上传速度 /// /// /// public delegate void UploadSpeedHandle(string filePath, int fileBolckNum, double totalSecond, long offset, long blockTotalLenth); public static event UploadSpeedHandle UploadSpeed; public static QuotaResult GetQuota(Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); var res = wc.DownloadString("http://pan.baidu.com/api/quota?checkexpire=1&checkfree=1"); var obj = JsonConvert.DeserializeObject(res); obj.success = true; return obj; } } catch (Exception ex) { return new QuotaResult() { exception = ex }; } } public static UserInfoResult GetUserInfo(Credential credential) { try { if (credential.Uid <= 0) throw new Exception("Invalid uid."); using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); var res = wc.DownloadString("http://pan.baidu.com/api/user/getinfo?user_list=[" + credential.Uid + "]"); var obj = JsonConvert.DeserializeObject(res); obj.success = true; return obj; } } catch (Exception ex) { return new UserInfoResult() { exception = ex }; } } public static FileListResult GetFileList(string path, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); var res = wc.DownloadString("http://pan.baidu.com/api/list?page=1&num=10000000&dir=" + HttpUtility.UrlEncode(path)); var obj = JsonConvert.DeserializeObject(res); obj.success = true; return obj; } } catch (Exception ex) { return new FileListResult() { exception = ex }; } } public static ThumbnailResult GetThumbnail(string path, Credential credential, int width = 125, int height = 90, int quality = 100) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); var res = wc.DownloadData("http://pcsdata.baidu.com/rest/2.0/pcs/thumbnail?app_id=250528&method=generate&path=" + HttpUtility.UrlEncode(path) + "&quality=" + quality + "&height=" + height + "&width=" + width); return new ThumbnailResult() { success = true, image = res }; } } catch (Exception ex) { return new ThumbnailResult() { exception = ex }; } } public static GetDownloadResult GetDownload(string path, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia"); var res = wc.DownloadString("http://d.pcs.baidu.com/rest/2.0/pcs/file?app_id=250528&method=locatedownload&ver=4.0&path=" + HttpUtility.UrlEncode(path)); var obj = JsonConvert.DeserializeObject(res); obj.success = true; return obj; } } catch (Exception ex) { return new GetDownloadResult() { exception = ex }; } } public static FileOperationResult CreateFolder(string path, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var str = "isdir=1&path=" + HttpUtility.UrlEncode(path); var res = wc.UploadData("http://pan.baidu.com/api/create?a=commit", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; return obj; } } catch (Exception ex) { return new FileOperationResult() { exception = ex }; } } public static FileOperationResult Copy(string path, string dest, string newname, Credential credential) { var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"dest\":\"" + HttpUtility.UrlEncode(dest) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]"; return FileOp("http://pan.baidu.com/api/filemanager?opera=copy&clienttype=8", str, credential); } public static FileOperationResult Delete(string path, Credential credential) { var str = "filelist=[\"" + HttpUtility.UrlEncode(path) + "\"]"; return FileOp("http://pan.baidu.com/api/filemanager?opera=delete&clienttype=8", str, credential); } public static FileOperationResult Move(string path, string dest, string newname, Credential credential) { var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"dest\":\"" + HttpUtility.UrlEncode(dest) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]"; return FileOp("http://pan.baidu.com/api/filemanager?opera=move&clienttype=8", str, credential); } public static FileOperationResult Rename(string path, string newname, Credential credential) { var str = "filelist=[{\"path\":\"" + HttpUtility.UrlEncode(path) + "\",\"newname\":\"" + HttpUtility.UrlEncode(newname) + "\"}]"; return FileOp("http://pan.baidu.com/api/filemanager?opera=rename&clienttype=8", str, credential); } private static FileOperationResult FileOp(string url, string str, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var res = wc.UploadData(url, Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); if (obj.info.Length == 0 && obj.errno != 0) return new FileOperationResult() { success = true, errno = obj.errno }; else if (obj.info.Length == 0 || obj.errno != 0 && obj.info[0].errno == 0) throw new Exception("Response data malformat."); else return new FileOperationResult() { success = true, errno = obj.info[0].errno, path = obj.info[0].path }; } } catch (Exception ex) { return new FileOperationResult() { exception = ex }; } } public static OfflineListResult GetOfflineList(Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); var res1 = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&method=list_task&need_task_info=1&status=255"); var ltr = JsonConvert.DeserializeObject(res1); if (ltr.task_info.Length == 0) return new OfflineListResult() { success = true, tasks = new OfflineListResult.Entry[0] }; var str = "method=query_task&op_type=1&task_ids=" + HttpUtility.UrlEncode(string.Join(",", ltr.task_info.Select(e => e.task_id.ToString()))); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var res2 = wc.UploadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528", Encoding.UTF8.GetBytes(str)); var qtr = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res2)); return new OfflineListResult() { tasks = ltr.task_info.Select(e => { var ai = qtr.task_info[e.task_id.ToString()]; return new OfflineListResult.Entry() { create_time = e.create_time, od_type = e.od_type, save_path = e.save_path, source_url = e.source_url, task_id = e.task_id, task_name = e.task_name, file_size = ai.file_size, finished_size = ai.finished_size, status = ai.status }; }).ToArray(), success = true }; } } catch (Exception ex) { return new OfflineListResult() { exception = ex }; } } public static Result CancelOfflineTask(long taskid, Credential credential) { return OfflineTaskOp(taskid, "cancel_task", credential); } public static Result DeleteOfflineTask(long taskid, Credential credential) { return OfflineTaskOp(taskid, "delete_task", credential); } public static Result ClearOfflineTask(Credential credential) { return OfflineTaskOp(0, "clear_task", credential); } private static Result OfflineTaskOp(long taskid, string oper, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.DownloadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&method=" + oper + "&task_id=" + taskid); return new Result() { success = true }; } } catch (Exception ex) { return new Result() { exception = ex }; } } public static QueryLinkResult QueryLinkFiles(string link, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia"); if (link.StartsWith("magnet:", StringComparison.OrdinalIgnoreCase)) { var res = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8&method=query_magnetinfo&source_url=" + HttpUtility.UrlEncode(link)); var obj = JsonConvert.DeserializeObject(res); return new QueryLinkResult() { success = true, files = obj.magnet_info }; } else if (link.EndsWith(".torrent", StringComparison.OrdinalIgnoreCase)) { var res = wc.DownloadString("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8&method=query_sinfo&type=2&source_path=" + HttpUtility.UrlEncode(link)); var obj = JsonConvert.DeserializeObject(res); return new QueryLinkResult() { success = true, files = obj.torrent_info.file_info }; } else throw new Exception("Not a magnet link or a torrent file."); } } catch (Exception ex) { return new QueryLinkResult() { exception = ex }; } } public static AddOfflineTaskResult AddOfflineTask(string link, string savepath, Credential credential, int[] selected = null, string sha1 = "") { try { var str = "method=add_task&save_path=" + HttpUtility.UrlEncode(savepath) + "&"; if (link.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || link.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) str += "type=0&source_url=" + HttpUtility.UrlEncode(link); else if (link.StartsWith("ed2k://", StringComparison.OrdinalIgnoreCase)) str += "type=3&source_url=" + HttpUtility.UrlEncode(link); else if (link.StartsWith("magnet:", StringComparison.OrdinalIgnoreCase)) str += "type=4&task_from=5&source_url=" + HttpUtility.UrlEncode(link) + "&selected_idx=" + string.Join(",", selected.Select(i => i.ToString())); else if (link.EndsWith(".torrent", StringComparison.OrdinalIgnoreCase)) str += "type=2&task_from=5&file_sha1=" + sha1 + "&source_path=" + HttpUtility.UrlEncode(link) + "&selected_idx=" + string.Join(",", selected.Select(i => i.ToString())); else throw new Exception("Link invalid."); using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia"); var res = wc.UploadData("http://pan.baidu.com/rest/2.0/services/cloud_dl?app_id=250528&clienttype=8", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; return obj; } } catch (Exception ex) { return new AddOfflineTaskResult() { exception = ex }; } } public static ShareResult Share(string[] pathlist, Credential credential, string pwd = null) { try { if (pwd != null && pwd.Length != 4) throw new Exception("Length of pwd must be 4."); var str = "path_list=[" + string.Join(",", pathlist.Select(p => '"' + HttpUtility.UrlEncode(p) + '"')) + "]&channel_list=[]&shorturl=1&"; if (pwd == null) str += "public=1&schannel=0"; else str += "public=0&schannel=4&pwd=" + pwd; var rand = new Random(); var logid = new string(Enumerable.Range(0, 100).Select(i => (char)('a' + rand.Next(26))).ToArray()); using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var res = wc.UploadData("http://pan.baidu.com/share/pset?clienttype=8&channel=00000000000000000000000000000000&version=5.4.5.4&devuid=123456&logid=" + logid, Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; return obj; } } catch (Exception ex) { return new ShareResult() { exception = ex }; } } public static TransferResult Transfer(string url, string path, Credential credential, string pwd = null) { try { using (var wc = new CookieAwareWebClient()) { wc.Cookies.Add(credential); var str = wc.DownloadString(url); var rurl = wc.ResponseUri.ToString(); string shareid = null, uk = null; if (rurl.Contains("/share/init")) { if (pwd == null) throw new Exception("Need password."); shareid = Regex.Match(rurl, "shareid=(\\d+)").Groups[1].Value; uk = Regex.Match(rurl, "uk=(\\d+)").Groups[1].Value; wc.Headers.Add(HttpRequestHeader.Referer, rurl); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var res = wc.UploadData("http://pan.baidu.com/share/verify?shareid=" + shareid + "&uk=" + uk, Encoding.UTF8.GetBytes("vcode=&vcode_str=&pwd=" + pwd)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); if (obj.errno != 0) throw new Exception("Password verification returned errno = " + obj.errno); str = wc.DownloadString(url); } str = Regex.Match(str, "yunData.setData(.*)").Groups[1].Value.Trim(); str = str.Substring(1, str.Length - 3); var obj2 = JsonConvert.DeserializeObject(str); str = "path=" + HttpUtility.UrlEncode(path) + "&filelist=[" + string.Join(",", obj2.file_list.list.Select(e => "\"" + HttpUtility.UrlEncode(e.path) + "\"")) + "]"; wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); wc.Headers.Add(HttpRequestHeader.Referer, url); var rand = new Random(); var logid = new string(Enumerable.Range(0, 100).Select(i => (char)('a' + rand.Next(26))).ToArray()); var res2 = wc.UploadData("http://pan.baidu.com/share/transfer?channel=chunlei&clienttype=0&web=1&app_id=250528&ondup=newcopy&async=1&shareid=" + shareid + "&from=" + uk + "&logid=" + logid + "&bdstoken=" + obj2.bdstoken, Encoding.UTF8.GetBytes(str)); var obj3 = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res2)); obj3.success = true; return obj3; } } catch (Exception ex) { return new TransferResult() { exception = ex }; } } public static CommitUploadResult SimpleUpload(string localpath, string remotepath, Credential credential, string host = "c.pcs.baidu.com") { try { var size = new FileInfo(localpath).Length; var mtime = (long)(new FileInfo(localpath).LastAccessTime.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; var md5 = UploadHelper.GetMD5HashFromFile(localpath); var str = "path=" + remotepath + "&size=" + size + "&isdir=0&block_list=[\"" + md5 + "\"]&autoinit=1&local_mtime=" + mtime + "&method=post"; using (var wc = new PatientWebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var res = wc.UploadData("http://pan.baidu.com/api/precreate?clienttype=8", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); if (obj.errno != 0) throw new Exception("precreate had errno = " + obj.errno); var boundary = GetBoundary(); wc.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary); str = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"name\"\r\nContent-Type: application/octet-stream\r\n\r\n"; var str2 = "\r\n--" + boundary + "--\r\n"; var data = Encoding.UTF8.GetBytes(str).Concat(File.ReadAllBytes(localpath)).Concat(Encoding.UTF8.GetBytes(str2)).ToArray(); res = wc.UploadData("http://" + host + "/rest/2.0/pcs/superfile2?app_id=250528&method=upload&path=" + HttpUtility.UrlEncode(remotepath) + "&uploadid=" + HttpUtility.UrlEncode(obj.uploadid) + "&partseq=0&partoffset=0", data); str = "path=" + remotepath + "&size=" + size + "&isdir=0&uploadid=" + HttpUtility.UrlEncode(obj.uploadid) + "&block_list=[\"" + md5 + "\"]&method=post&rtype=2&sequence=1&mode=1&local_mtime=" + mtime; res = wc.UploadData("http://pan.baidu.com/api/create?a=commit&clienttype=8", Encoding.UTF8.GetBytes(str)); var obj2 = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj2.success = true; return obj2; } } catch (Exception ex) { return new CommitUploadResult() { exception = ex }; } } public static RapidUploadResult RapidUpload(FileProperty prop, string path, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var str = "path=" + HttpUtility.UrlEncode(path) + "&content-length=" + prop.size + "&content-md5=" + prop.md5 + "&slice-md5=" + prop.slice_md5 + "&content-crc32=" + prop.crc32 + "&local_mtime=" + prop.mtime + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&rtype=2"; var res = wc.UploadData("http://pan.baidu.com/api/rapidupload?clienttype=8", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; return obj; } } catch (Exception ex) { return new RapidUploadResult() { exception = ex }; } } public static InitUploadResult InitUpload(FileProperty prop, string path, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var str = "path=" + HttpUtility.UrlEncode(path) + "&size=" + prop.size + "&isdir=0&local_mtime=" + prop.mtime + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&autoinit=1&method=post"; var res = wc.UploadData("http://pan.baidu.com/api/precreate?clienttype=8", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; if (InitUploadFile != null && obj.errno == 0) { InitUploadFile(prop.path, prop.blocks.Length, obj.block_list.Length); } return obj; } } catch (Exception ex) { return new InitUploadResult() { exception = ex }; } } public static Result UploadBlock(FileProperty prop, string path, InitUploadResult session, FileStream stream, int blockid, string host, Credential credential) { try { using (var wc = new PatientWebClient()) { if (StartUploadBlock != null) { StartUploadBlock(prop.path, blockid + 1, prop.blocks.Length); } var boundary = GetBoundary(); wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "multipart/form-data; boundary=" + boundary); var str = "--" + boundary + "\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"name\"\r\nContent-Type: application/octet-stream\r\n\r\n"; var str2 = "\r\n--" + boundary + "--\r\n"; stream.Seek((long)blockid * UploadHelper.BlockLen, SeekOrigin.Begin); var fdata = new byte[UploadHelper.BlockLen]; var len = stream.Read(fdata, 0, fdata.Length); if (len < fdata.Length) { var arr = new byte[len]; Array.Copy(fdata, arr, len); fdata = arr; } var data = Encoding.UTF8.GetBytes(str).Concat(fdata).Concat(Encoding.UTF8.GetBytes(str2)).ToArray(); var res = wc.UploadData("http://" + host + "/rest/2.0/pcs/superfile2?app_id=250528&method=upload&path=" + HttpUtility.UrlEncode(path) + "&uploadid=" + HttpUtility.UrlEncode(session.uploadid) + "&partseq=" + blockid + "&partoffset=" + (long)blockid * UploadHelper.BlockLen, data); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); if (obj.md5 != prop.blocks[blockid]) throw new Exception("MD5 mismatch."); if (ComplateUploadBlock != null) { ComplateUploadBlock(prop.path, blockid + 1, prop.blocks.Length); } return new Result() { success = true }; } } catch (Exception ex) { return new Result() { exception = ex }; } } private static Result UploadWithWebrequest(FileProperty prop, string path, InitUploadResult session, FileStream stream, int blockid, string host, Credential credential) { var boundary = GetBoundary(); string url = $"http://{host}/rest/2.0/pcs/superfile2?app_id=250528&method=upload&path={HttpUtility.UrlEncode(path)}&uploadid={HttpUtility.UrlEncode(session.uploadid)}&partseq={blockid}&partoffset={(long)blockid * UploadHelper.BlockLen}"; var webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Headers.Add("Cookie", credential); //对发送的数据不使用缓存 webRequest.AllowWriteStreamBuffering = false; //设置获得响应的超时时间(300秒) webRequest.Timeout = 300000; webRequest.ContentType = "multipart/form-data; boundary=" + boundary; webRequest.Method = "POST"; var startBoundaryBytes = Encoding.ASCII.GetBytes("--" + boundary + "\r\nContent-Disposition: form-data; name=\"filename\"; filename=\"name\"\r\nContent-Type: application/octet-stream\r\n\r\n"); var endBoundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); stream.Seek((long)blockid * UploadHelper.BlockLen, SeekOrigin.Begin); var fdata = new byte[UploadHelper.BlockLen]; var len = stream.Read(fdata, 0, fdata.Length); if (len < fdata.Length) { var arr = new byte[len]; Array.Copy(fdata, arr, len); fdata = arr; } var fdataStream = new MemoryStream(fdata); long totalLen = len + startBoundaryBytes.Length + endBoundaryBytes.Length; webRequest.ContentLength = totalLen; try { int bufferLen = 4 * 1024; byte[] buffer = new byte[bufferLen]; long offset = 0; DateTime startTime = DateTime.Now; Stream postStream = webRequest.GetRequestStream(); postStream.Write(startBoundaryBytes, 0, startBoundaryBytes.Length); do { var size = fdataStream.Read(buffer, 0, bufferLen); if (size <= 0) { break; } offset += size; postStream.Write(buffer, 0, size); TimeSpan span = DateTime.Now - startTime; double second = span.TotalSeconds; if (UploadSpeed != null) { UploadSpeed(prop.path, blockid + 1, second, offset, fdata.LongLength); } //Console.WriteLine("已用时:" + second.ToString("F2") + "秒"); //Console.WriteLine(" 平均速度:" + (offset / 1024 / second).ToString("0.00") + "KB/秒"); //Console.WriteLine("已上传:" + (offset * 100.0 / fdata.Length).ToString("F2") + "%"); } while (true); postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length); postStream.Close(); var responseSteam = webRequest.GetResponse().GetResponseStream(); StreamReader sr = new StreamReader(responseSteam, Encoding.UTF8); var obj = JsonConvert.DeserializeObject(sr.ReadToEnd()); if (obj.md5 != prop.blocks[blockid]) throw new Exception("MD5 mismatch."); if (ComplateUploadBlock != null) { ComplateUploadBlock(prop.path, blockid + 1, prop.blocks.Length); } return new Result() { success = true }; } catch (Exception ex) { return new Result() { exception = ex }; } } public static CommitUploadResult CommitUpload(FileProperty prop, string path, InitUploadResult session, Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded"); var str = "path=" + HttpUtility.UrlEncode(path) + "&size=" + prop.size + "&isdir=0&uploadid=" + HttpUtility.UrlEncode(session.uploadid) + "&block_list=[" + string.Join(",", prop.blocks.Select(h => '"' + h + '"')) + "]&method=post&rtype=2&sequence=1&mode=1&local_mtime=" + prop.mtime; var res = wc.UploadData("http://pan.baidu.com/api/create?a=commit&clienttype=8", Encoding.UTF8.GetBytes(str)); var obj = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(res)); obj.success = true; if (UpdateComplate != null) { UpdateComplate(prop.path); } return obj; } } catch (Exception ex) { return new CommitUploadResult() { exception = ex }; } } public static CommitUploadResult ChunkedUpload(string localpath, string remotepath, Credential credential) { try { var servers = GetUploadServers(credential); if (!servers.success) throw servers.exception; var prop = UploadHelper.GetFileProperty(localpath); var session = InitUpload(prop, remotepath, credential); if (!session.success) throw session.exception; if (session.errno != 0) throw new Exception("Init upload returned errno = " + session.errno); using (var fs = new FileStream(localpath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { for(int i = 0; i < prop.blocks.Length; i++) { var res = UploadBlock(prop, remotepath, session, fs, i, servers.servers[0], credential); //var res = UploadWithWebrequest(prop, remotepath, session, fs, i, servers.servers[0], credential); if (!res.success) throw res.exception; } } var comres = CommitUpload(prop, remotepath, session, credential); if (!comres.success) throw comres.exception; if (comres.errno != 0) throw new Exception("Commit upload returned errno = " + comres.errno); return comres; } catch (Exception ex) { throw ex; } } public static GetUploadServersResult GetUploadServers(Credential credential) { try { using (var wc = new WebClient()) { wc.Headers.Add(HttpRequestHeader.Cookie, credential); wc.Headers.Add(HttpRequestHeader.UserAgent, "netdisk;5.4.5.4;PC;PC-Windows;10.0.14393;WindowsBaiduYunGuanJia"); var res = wc.DownloadString("http://d.pcs.baidu.com/rest/2.0/pcs/file?app_id=250528&method=locateupload&esl=1&ehps=0&upload_version=2.0"); var obj = JsonConvert.DeserializeObject(res); return new GetUploadServersResult() { success = true, servers = obj.servers.Select(s => Regex.Match(s.server, ":\\/\\/(.+)$").Groups[1].Value).ToArray() }; } } catch (Exception ex) { return new GetUploadServersResult() { exception = ex }; } } private static string GetBoundary() { var rand = new Random(); var sb = new StringBuilder(); for (int i = 0; i < 28; i++) sb.Append('-'); for (int i = 0; i < 15; i++) sb.Append((char)(rand.Next(0, 26) + 'a')); var boundary = sb.ToString(); return boundary; } private class FileOpResult { public int errno; public Entry[] info; public class Entry { public int errno; public string path; } } private class ListTaskResult { public Entry[] task_info; public class Entry { public long create_time; public int od_type; public string save_path; public string source_url; public long task_id; public string task_name; } } private class QueryTaskResult { public Dictionary task_info; public class Entry { public long file_size; public long finished_size; public int status; } } private class QueryTorrentResult { public TorrentInfo torrent_info; public class TorrentInfo { public QueryLinkResult.Entry[] file_info; public string sha1; } } private class QueryMagnetResult { public QueryLinkResult.Entry[] magnet_info; } private class VerifyPwdResult { public int errno; } private class SharePageData { public string bdstoken; public FileList file_list; public class FileList { public Entry[] list; public class Entry { public string path; } } } private class SuperFileResponse { public string md5; } private class LocateUploadResponse { public Entry[] servers; public class Entry { public string server; } } } }