用ASP.NET读取QQ相册

news/2024/11/9 5:02:09/

 最近遇到要读取QQ相册的问题,所以自己诼磨了下,把读取相册的思路和代码写下来。 

      很多网站到图片链接都做了盗链处理。意思是如果你想在不是他的网站上引用图片就不会正确显示图片,而是一张其它的版权说明之类的图片。实现防盗链的一般做好是通过判断Request的Headers中的Referer属性。该属性保存着客户端在访问该链接之前的地址。又如我访问http://www.domain.com/,该网站中有一张图片<img src='http://www.qq.com/logo.gif'> ,该图片请求的Referer属性就应该是http://www.domain.com/ 表示是从该地址转过来的。

      要突破这种防盗链,你可以在发请求这前修改Referer属性,不过这有点难度。因为这个属性是只读的。另外一种做法是用程序的方式(在ASP.NET中即HttpWebRequest)来新建一个请求,些时Referer是空的,所以防盗链也就不起作用。

     QQ相册取图片的方式隐藏得很好,是用Ajax方式读取的,js脚本文件也进行了压缩,所以很难看清它是怎么取图片的。看了很久之后才发现它读相册以及相册中图片的地址:
  相册地址:http://p{0}.photo.qq.com/{1}/16  //{0} = {1} % 13 + 1 {1}为qq号
  图片地址:http://sz.photo.store.qq.com/http_staload.cgi?{0}/{1} ; //{0}qq号 {1}相册号
这两个地址只是返回一个XML文件,文件中才标识着真正的图片地址。

     程序的思路是先通过QQ号得到相册相关信息的xml文件,从文件中得到相册号和相册封面图片地址,用HttpWebRequest得到该封面图片并显示出来。当用户点击该图片时再根据相册号得到该相册下图片信息的xml文件,再次用HttpWebRequest的方式显示预览图片,供用户选择要导入的图片,最好根据图片的真正地址把图片保存在当前文件夹中。

     把程序贴在下面,一个面页GetPhoto.aspx和后台代码GetPhoto.aspx.cs

GetPhoto.aspx

 

<%@ Page language="c#"  CodeFile="GetPhoto.aspx.cs" AutoEventWireup="false" Inherits="GetPhoto" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
    
<HEAD>
        
<title>GetPhoto</title>
        
<meta content="Microsoft Visual Studio .NET 7.1" name="GENERATOR">
        
<meta content="C#" name="CODE_LANGUAGE">
        
<meta content="JavaScript" name="vs_defaultClientScript">
        
<meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
    
</HEAD>
    
<body>
        
<form id="Form1" method="post" runat="server">
            
<P>QQ号码:<asp:textbox id="txtQQ" runat="server"></asp:textbox>
                
<asp:button id="Button1" runat="server" Text="读取相册"></asp:button></P>
            
<asp:Label ID="msg" Runat="server"></asp:Label>&nbsp;
            
<asp:Button ID="Button3" runat="server" OnClick="Button3_Click" Text="全选" />
            
<asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="全不选" /><P>
                
<asp:DataList id="albumList" Runat="server" RepeatColumns="8" EnableViewState="False">
                    
<ItemTemplate>
                        
<div>
                            
<div><%# DataBinder.Eval(Container.DataItem,"PicLink")%></div>
                            
<div><%# DataBinder.Eval(Container.DataItem,"PicTitle")%></div>
                        
</div>
                    
</ItemTemplate>
                
</asp:DataList>
                
<asp:DataList id="picList" Runat="server" RepeatColumns="8" EnableViewState="False" DataKeyField="PicUrl">
                    
<ItemTemplate>
                        
<div>
                            
<div><%# DataBinder.Eval(Container.DataItem,"PicLink")%></div>
                            
<div>
                                
<asp:CheckBox ID="confirm" Runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"PicTitle")%>' /></div>
                                
                        
</div>
                    
</ItemTemplate>
                    
<FooterTemplate>
                        
<div>
                            
<asp:Button ID="bntOk" Runat="server" CommandName="Update" Text="开始导入"></asp:Button></div>
                        
                                            
</FooterTemplate>
                
</asp:DataList>
            
</P>
        
</form>
    
</body>
</HTML>


用了两个DataList 一个用来显示相册图片,一个用来显示相册中的图片。

后台代码GetPhoto.aspx.cs  稍微有点长

using System;
using System.Collections;
using System.Data;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Net;
using System.IO;
using System.Xml;
using System.Drawing.Imaging;


    
/**//// <summary>
    
/// GetPhoto 的摘要说明。
    
/// </summary>
    public partial class GetPhoto : System.Web.UI.Page
    {
        
//protected System.Web.UI.WebControls.TextBox txtQQ;
        
//protected System.Web.UI.WebControls.Button Button1;
        
//protected System.Web.UI.WebControls.DataList picList; //{0}qq号
        
//protected System.Web.UI.WebControls.Label msg;  
        
//protected System.Web.UI.WebControls.DataList albumList;
    
        
private const string QQPHOTO = "http://p{0}.photo.qq.com/{1}/16"//{0} = {1} % 13 + 1 {1}为qq号
        
//取相册的另一个有用路径,在第一个可用的情况下用。
        private const string QQPHOTO_B = "http://photo.qq.com/cgi-bin/common/cgi_list_album?uin={0}";
        
private const string ALBUMURL = "http://sz.photo.store.qq.com/http_staload.cgi?{0}/{1}"//{0}qq号 {1}album号
        
        
private string UserID = "maxwell"//用户名

        
private void Page_Load(object sender, System.EventArgs e)
        {
            
//点击“开始导入”时 把打勾的图片保存到本机上。
            picList.UpdateCommand += new DataListCommandEventHandler(picList_UpdateCommand);

            
//取url参数中的相册图片 即取qq相册   QQ有防盗链
            if(Request.QueryString["pre"!= null
            {
                
string url = Request.QueryString["pre"];

                WebRequest preR 
= WebRequest.Create(url);
                Stream stream 
= preR.GetResponse().GetResponseStream();
                
//QQ相册只能上传jpg|gif|png的图片
                
//把这些图片保存为jpeg格式和ContentType设置为image/jpeg都能显示。
                Response.ClearContent();
                Response.ContentType 
= "image/jpeg";

                System.Drawing.Bitmap img 
= new System.Drawing.Bitmap(stream);        
                img.Save(Response.OutputStream,ImageFormat.Jpeg);

                img.Dispose();
                stream.Close();

                Response.End();
            }

            
//根据相册ID取该相册中的图片。
            if(Request.QueryString["id"!= null && Request.QueryString["qq"!= null)
            {
                
string id = Request.QueryString["id"];
                
string qq = Request.QueryString["qq"];
                
string albumUrl = string.Format(ALBUMURL,qq,id);
                
                XmlDocument xml 
= GetXmlData(albumUrl);
                
if(xml == null)
                {
                    msg.Text 
= "暂时不能读取数据。请稍后再试。";
                    
return;
                }
                XmlNodeList list 
= xml.GetElementsByTagName("pic");

                PicAlbum[] pics 
= new PicAlbum[list.Count];

                
for(int i=0; i<list.Count; i++)
                {
                    
string name = list[i].SelectSingleNode("name").InnerText;
                    
string pre = list[i].SelectSingleNode("pre").InnerText;
                    
string url = list[i].SelectSingleNode("url").InnerText;
                
                    
string picLink = "<img src='" + Request.Url.AbsolutePath + "?pre=" + pre + "'/>";
                    pics[i] 
= new PicAlbum(url,picLink,name);
                }
                albumList.Visible 
= false;
                picList.Visible 
= true;
                picList.DataSource 
= pics;
                picList.DataBind();
            }
    }

        
#region Web 窗体设计器生成的代码
        
override protected void OnInit(EventArgs e)
        {
            
//
            
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
            
//
            InitializeComponent();
            
base.OnInit(e);
        }
        
        
/**//// <summary>
        
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
        
/// 此方法的内容。
        
/// </summary>
        private void InitializeComponent()
        {    
            
this.Button1.Click += new System.EventHandler(this.Button1_Click);
            
this.Load += new System.EventHandler(this.Page_Load);

        }
        
#endregion

        
//读取相册
        private void Button1_Click(object sender, System.EventArgs e)
        {
            
string qq = txtQQ.Text;
            
string photoUrl = string.Format(QQPHOTO,(int.Parse(qq)%13+1),qq);
            
            
//从QQ读取相册数据
            XmlDocument xml = GetXmlData(photoUrl);
            
if(xml == null)
            {
                
//判断静态XML是否取到,如果未取到,再尝试拉一次CGI(QQ的说法)
                string photoBackupUrl = string.Format(QQPHOTO_B,qq);
                xml 
= GetXmlData(photoBackupUrl);
                
if(xml == null)
                {
                    msg.Text 
= "暂时不能读取数据。请稍后再试。";
                    
return;
                }
            }
            XmlNodeList list 
= xml.GetElementsByTagName("album");
            
            ArrayList albums 
= new ArrayList();
            
for(int i=1; i<list.Count; i++)//从1开始,是因为xml文件的第一个album不是相册数据。
            {
                
string priv = list[i].SelectSingleNode("priv").InnerText.Trim();
                
if(priv != "1")
                    
continue;
                
string id = list[i].SelectSingleNode("id").InnerText;
                
string name = list[i].SelectSingleNode("name").InnerText;
                
string pre = list[i].SelectSingleNode("pre").InnerText;
                
                
string picLink = "<a href='"+ Request.Url.AbsolutePath + "?id=" + id +"&qq=" + qq + "'><img src='" + Request.Url.AbsolutePath + "?pre=" + pre + "'/></a>";
                albums.Add(
new PicAlbum(id,picLink,name));
                
            }
            picList.Visible 
= false;
            albumList.Visible 
= true;
            albumList.DataSource 
= albums;
            albumList.DataBind();
        }


        
/**//// <summary>
        
/// 根据地址得到一个xml文档
        
/// </summary>
        
/// <param name="url">地址</param>
        
/// <returns></returns>
        private XmlDocument GetXmlData(string url)
        {
            HttpWebRequest wreq 
= (HttpWebRequest)WebRequest.Create(url);
            
//wreq.Timeout = 20;
            HttpWebResponse wres = null;
            XmlDocument xml 
= null;
            
try
            {
                wres 
= (HttpWebResponse)wreq.GetResponse();
                xml 
= new XmlDocument();
                xml.Load(wres.GetResponseStream());
            }
            
finally
            {
                wres.Close();
            }
            
return xml;
        }

        
/**//// <summary>
        
/// 开始导入图片  只把打勾的图片导入。
        
/// </summary>
        
/// <param name="source"></param>
        
/// <param name="e"></param>
        private void picList_UpdateCommand(object source, DataListCommandEventArgs e)
        {
            DataList picList 
= source as DataList;
            PicAlbum[] pics 
= (PicAlbum[])picList.DataSource;
            ArrayList urls 
= new ArrayList(); //用来保存要导入图片的地址。
            for(int i=0; i<picList.Items.Count; i++)
            {
                CheckBox cb 
= (CheckBox)picList.Items[i].FindControl("confirm");
                
if(cb.Checked)
                {
                    urls.Add(picList.DataKeys[i]);
                }
            }
            
//读取要保存图片的URL后,保存图片
            SavePics(urls);
        }

        
//全选
        protected void Button3_Click(object sender, EventArgs e)
        {

            PicAlbum[] pics 
= (PicAlbum[])picList.DataSource;
            
for (int i = 0; i < picList.Items.Count; i++)
            {
                CheckBox cb 
= (CheckBox)picList.Items[i].FindControl("confirm");
                
if (cb.Checked == false)
                {
                    cb.Checked 
= true;
                }
            }
        }

        
/**//// <summary>
        
/// 保存列表中的图片。
        
/// </summary>
        
/// <param name="urls">保存图片地址的列表</param>
        private void SavePics(ArrayList urls)
        {
            DateTime date 
= DateTime.Now;
            
string path = Server.MapPath(".");
            
int i=1;
            
foreach(string url in urls)
            {
                
string name = path + "//" + UserID + date.ToString("yyyyMMdd"+ date.Hour.ToString() + date.Minute.ToString() + date.Second.ToString()   + (i++)  + ".jpg";
                HttpWebRequest req 
= (HttpWebRequest)WebRequest.Create(url);
                Stream stream 
= req.GetResponse().GetResponseStream();

                System.Drawing.Bitmap img 
= new System.Drawing.Bitmap(stream);        
                img.Save(name,ImageFormat.Jpeg);

                img.Dispose();
                stream.Close();
            }
            msg.Text 
= "文件保存完成。";
        }

        
//全不选
        protected void Button2_Click(object sender, EventArgs e)
        {
            PicAlbum[] pics 
= (PicAlbum[])picList.DataSource;
            
for (int i = 0; i < picList.Items.Count; i++)
            {
                CheckBox cb 
= (CheckBox)picList.Items[i].FindControl("confirm");
                
if (cb.Checked == true)
                {
                    cb.Checked 
= false;
                }
            }
        }
}

    
/**//// <summary>
    
/// 图片相册类
    
/// </summary>
    public class PicAlbum
   {
        
private string picUrl;
        
private string picLink;
        
private string picTitle;

        
public PicAlbum(string picurl,string piclink,string pictitle)
        {
            picUrl 
= picurl;
            picLink 
= piclink;
            picTitle 
= pictitle;
        }

        
public string PicUrl
        {
            
getreturn picUrl;}
        }
        
public string PicLink
        {
            
getreturn picLink;}
        }
        
public string PicTitle
        {
            
getreturn picTitle;}
        }
    }

 


http://www.ppmy.cn/news/350473.html

相关文章

AndroidRecyclerView仿QQ相册功能

实例模仿新版QQ相册功能&#xff0c;RecyclerView实现相册选择&#xff0c;DiskLruCache实现图片缓存&#xff0c;ItemTouchHelper实现图片的拖拽排序&#xff0c;单线程轮播解决加载大量图片卡顿问题&#xff08;参考&#xff1a;http://blog.csdn.net/lishengko/article/deta…

1秒破解iPhone 13 Pro:可任意获取并删除设备上的数据

整理 | 祝涛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 据报道&#xff0c;在第四届“天府杯”国际网络安全大赛上&#xff0c;奇安盘古旗下盘古实验室的白帽黑客slipper完成了iPhone 13 Pro的全球首次公开远程越狱&#xff0c;取得手机最高控制权限&#x…

【C++】红黑树的模拟实现

文章目录 一、红黑树的概念二、红黑树的性质三、红黑树节点的定义四、红黑树结构五、红黑树的插入操作六、红黑树的调整1.叔叔存在且为红2.叔叔不存在或者存在且为黑3.插入完整代码4.总结 七、红黑树的验证八、红黑树的删除九、红黑树与AVL树的比较十、红黑树的应用十一、红黑树…

iphone app 破解网站集

最强的&#xff0c;最专业的破解软件网站合集&#xff0c;安全可靠&#xff0c;真正的的海量破解软件&#xff0c;从此不再为寻找app而苦恼 http://www.apptism.com/ http://ihacks.ru/ http://idownloads.ru/ http://www.spaziocellulare.com/ispazio/ http://iphonefreakz.co…

type T N 与 type T = N 的区别

问题引入 不知道大家跟我有没有同样的疑惑&#xff0c;Go 语言中的两种声明类型的方式有什么不同&#xff1f;我们为什么不用第二种方式来声明结构体呢&#xff1f; type A struct {n ints string }type B struct {n ints string }这篇文章&#xff0c;我们尝试来解答一下这…

【算法】Tiling a Rectangle with the Fewest Squares 铺瓷砖

文章目录 Tiling a Rectangle with the Fewest Squares 铺瓷砖问题描述&#xff1a;分析代码 Tiling a Rectangle with the Fewest Squares 铺瓷砖 问题描述&#xff1a; 房子的客厅大小为 n x m&#xff0c;为保持极简的风格&#xff0c;需要使用尽可能少的 正方形 瓷砖来铺…

vm虚拟机dnf过检测

多开搬砖无压力 q2733220961

虚拟机dnf连接服务器失败,用虚拟机登录dnf没法登录

方法/步骤 1.我们可以继续等待&#xff0c;不过通常如果出现正在连接服务器&#xff0c;一直就进不去游戏&#xff0c;1分钟之内还是有希望进入的&#xff0c;如果操作一分钟基本就进去不了了。 2.之后我们可以点击重新连接&#xff0c;我们在试一下&#xff0c;一般重新连接是…