草庐IT

.Net6/C# 百度网盘下载实例

路小乙 2023-04-11 原文

前置要求:有百度账号,实名认证以及开发者认证,创建应用并获取到关键凭证:Appid、Appkey、Secretkeyk和Signkey

                  平台上入门十分清楚,直接对着逐步操作即可,个人开发者审核也很快

百度网盘开放平台地址如下:https://pan.baidu.com/union/doc/nksg0sbfs

因为平台代码例子竟然没有C# ,这里主要是放授权以及下载部分代码实例

第一步:获取AuthorizeCode

string authorizeURL = @"http://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=你的AppKey&redirect_uri=oob&scope=basic,netdisk&device_id=你的AppID";

其中那个redirect_uri=oob的oob是一个默认返回l,如果有确切的返回链接可以写进去,如果没有就用oob

这里APIDemo类型的例子,直接把上面的代码粘进浏览器,会出一个固定的百度授权页面,授权一次既可,授权后就能拿到授权码,后续只要这个连接,就直接是授权码页面,具体如下:

 

 

第二步:通过授权码AuthorizeCode获取真正后续使用的AccessToken凭证

using (HttpClient client = new HttpClient())
{
   //换取AccessToken凭证
   string tokenURL = @"https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=上一个步骤拿到的授权码&client_id=你的AppKey&client_secret=你的SecretKey&redirect_uri=oob";

   HttpResponseMessage result = client.GetAsync(tokenURL).Result;
   string responseResult = result.Content.ReadAsStringAsync().Result;
client.Dispose();

}

其中responseResult即为带有access_token(接收令牌)的Json字符串,

还有两个重要的返回数据refresh_token(刷新令牌)以及expires_in(Access Token有效期(秒))

换算一下具体数据 ,access_token为12小时有效期,refresh_token有效期返回数据里没有,但从官网可知为10年

当天后续测试既可一直使用该access_token,

如果第二天开发再使用,用refresh_token通过刷新方法获取一下新的access_token以及refresh_token既可

刷新AccessToken的方法如下:

using (HttpClient client = new HttpClient())
{
   //刷新AccessToken凭证
   string refreshURL = @"https://openapi.baidu.com/oauth/2.0/token?grant_type=refresh_token&refresh_token=你的刷新令牌&client_id=你的AppKey&client_secret=你的SecretKey";

   HttpResponseMessage result = client.GetAsync(tokenURL).Result;
   string responseResult = result.Content.ReadAsStringAsync().Result;
client.Dispose(); }

responseResult即为带有新access_token的Json字符串

 

第三步:已有access_token,获取文件列表

using (HttpClient client = new HttpClient())
{
  string filelistURL = @"http://pan.baidu.com/rest/2.0/xpan/multimedia?method=listall&path=/BaiduCloudDiskDemo&access_token=你的接收令牌&web=1&recursion=1&start=0&limit=5";
  HttpResponseMessage result = client.GetAsync(filelistURL).Result;
  string responseResult = result.Content.ReadAsStringAsync().Result;
  FileList fileList = JsonConvert.DeserializeObject<FileList>(responseResult);
  client.Dispose();
}

FileList是根据返回的JSon字符串里的具体数据自定义实体类

filelist即为总的文件信息列表

web为是否返回缩略图地址,1为返回,0为不返回

recursion为是否递归,1为递归,0为不递归

start为查询起点,默认为0

limit为查询数量,默认为1000

补充FileList实体类的具体代码方便复制,正式项目中建议换个名字,Demo里是我随便起的:

    public class FileList
    {
        public int cursor { get; set; }
        public string errmsg { get; set; }
        public int errno { get; set; }
        public int has_more { get; set; }
        public List<ListItem> list { get; set; }
        public string request_id { get; set; }
    }
    public class ListItem
    {
        public int category { get; set; }
        public Int64 fs_id { get; set; }
        public int isdir { get; set; }
        public int local_ctime { get; set; }
        public int local_mtime { get; set; }
        public string md5 { get; set; }
        public string path { get; set; }
        public int server_ctime { get; set; }
        public string server_filename { get; set; }
        public int server_mtime { get; set; }
        public int size { get; set; }
        public Thumbs thumbs { get; set; }
    }
    public class Thumbs
    {
        public string icon { get; set; }
        public string url1 { get; set; }
        public string url2 { get; set; }
        public string url3 { get; set; }
        public string url4 { get; set; }
    }

 

 

第四步:文件列表成功,获取带有下载地址DLink的具体文件信息

using (HttpClient client = new HttpClient())
{
     //文件列表的fs_id组成的数组,再进行后续操作
     string arr = "";
     foreach (ListItem item in filelist.list)
     {
         arr = arr + item.fs_id.ToString() + ",";
     }
     arr = arr.TrimEnd(',');
string filedlinkURL = @"http://pan.baidu.com/rest/2.0/xpan/multimedia?method=filemetas&access_token=你的接收令牌&fsids=[" + arr + "]&thumb=1&dlink=1&extra=1"; HttpResponseMessage result = client.GetAsync(filedlinkURL).Result; string responseResult = result.Content.ReadAsStringAsync().Result; FileList_DLink fileList_dlink = JsonConvert.DeserializeObject<FileList_DLink>(responseResult); client.Dispose(); }

FileList_DLink是根据返回的JSon字符串里的具体数据自定义实体类

filelist_dlink为带有下载地址的文件信息

thumb为是否需要缩略图地址 0为否,1为是,默认为0

dlink为是否需要下载地址,0为否,1为是,默认为0

extra为是否需要拍摄时间、原图分辨率等其他信息,0 否、1 是,默认0

补充FileList_DLink实体类的具体代码方便复制,正式项目中类名最好改了,Demo是我随便起的:

    public class FileList_DLink
    {
        public string errmsg { get; set; }
        public int errno { get; set; }
        public List<ListItem_Dlink> list { get; set; }
        public ShareItem names { get; set; }
        public string request_id { get; set; }
    }
    public class ListItem_Dlink
    {
        public int category { get; set; }
        public int date_taken { get; set; }
        public string dlink { get; set; }
        public string filename { get; set; }
        public Int64 fs_id { get; set; }
        public int height { get; set; }
        public int isdir { get; set; }
        public string md5 { get; set; }
        public int oper_id { get; set; }
        public string path { get; set; }
        public int server_ctime { get; set; }
        public int server_mtime { get; set; }
        public int size { get; set; }
        public Thumbs_Dlink thumbs { get; set; }
        public int width { get; set; }

    }
    public class Thumbs_Dlink
    {
        public string icon { get; set; }
        public string url1 { get; set; }
        public string url2 { get; set; }
        public string url3 { get; set; }
        public string url4 { get; set; }

    }
    public class ShareItem
    {
        public string account { get; set; }
    }

 

 

第五步,具体文件信息下载成功,通过dlink下载地址下载文件到本地

HttpClientHandler hander = new HttpClientHandler();
hander.AllowAutoRedirect = true;
using (HttpClient client = new HttpClient(hander))
{
    if (filelist_dlink != null)//获取文件下载地址列表成功  下载文件
    {
         foreach (ListItem_Dlink item in filelist_dlink.list)
         {
              string filedownloadURL = @"" + item.dlink + "&access_token=你的接收令牌";
              HttpResponseMessage result = client.GetAsync(filedownloadURL).Result;
              if (result.StatusCode == HttpStatusCode.OK)
               {
                   string responseResult = result.Content.ReadAsStringAsync().Result;
               }
               else if (result.StatusCode == HttpStatusCode.Redirect)
               {
                    string AbsoluteUri = result.Headers.Location.AbsoluteUri;
                    result = client.GetAsync(AbsoluteUri).Result;
                    byte[] urlContents = client.GetByteArrayAsync(AbsoluteUri).Result;
                    string path = Environment.CurrentDirectory + "\\DownloadImg\\";
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                     }
                     path = path + item.filename;
                     using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
                     {
                          fs.Write(urlContents, 0, urlContents.Length);
                     }
                }
           }
      }
}

这里面做了一个重定向判断,

当时测试的时候一直返回302,后面是在判断为重定向的情况下将图片下载到本地的,可根据实际情况自行调整

以上,整个下载流程结束。

 

有关.Net6/C# 百度网盘下载实例的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  3. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  4. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  5. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  6. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  7. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  8. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  9. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  10. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

随机推荐