最近遇到要读取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
        {
            get{ return picUrl;}
        }
        public string PicLink
        {
            get{ return picLink;}
        }
        public string PicTitle
        {
            get{ return picTitle;}
        }
    }

用ASP.NET读取QQ相册相关推荐

  1. 在“后台反复读取用户相册”?微信回应:最新版本将取消

    昨日,有网友反映,iOS版微信.QQ.淘宝等多款App在后台反复读取用户相册. 根据用户描述,开启新版iOS 15的"隐私"功能有"记录APP活动",可以存储7 ...

  2. 模拟QQ相册上传图片

    1.模拟QQ相册上传图片 public class Demo05 {public static void main(String[] args) throws IOException {File fi ...

  3. QQ 相册后台存储架构重构与跨 IDC 容灾实践

    欢迎大家前往云加社区,获取更多腾讯海量技术实践干货哦~ 作者简介:xianmau,2015 年加入腾讯 TEG 架构平台部,一直负责 QQ 相册平台的维护和建设,主导相册上传架构重构和容灾优化等工作. ...

  4. QQ相册后台存储架构重构与跨IDC容灾实践

    写在前面:QQ 相册作为重量级资深业务,稳定运营.有效容灾,一直是相册团队追求的目标.QQ 相册架构一直在演变进化,本文重点介绍相册最新的一次重构细节.重构进行了大规模的存储搬迁.功能模块合并,抽象了 ...

  5. java 读取QQ邮箱

    1.引入jar包 <dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api ...

  6. 微信真的在后台频繁读取用户相册吗?

    数据智能产业创新服务媒体 --聚焦数智 · 改变商业 <数据安全法>和<个人信息保护法>落地以后,用户隐私越来越被大家所重视.这不,最近微信又上了热搜,起因是有用户开启了iOS ...

  7. AndroidRecyclerView仿QQ相册功能

    实例模仿新版QQ相册功能,RecyclerView实现相册选择,DiskLruCache实现图片缓存,ItemTouchHelper实现图片的拖拽排序,单线程轮播解决加载大量图片卡顿问题(参考:htt ...

  8. ASP.net 仿QQ弹出窗口

    ASP.net 仿QQ弹出窗口 [转]http://hi.baidu.com/liyukun8203/blog/item/d9244dfcdb78e388b901a019.html 最近在做内部管理, ...

  9. qq相册传照片显示服务器,为什么上传到QQ空间的高清照片,时间一长就变得模糊了?...

    原标题:为什么上传到QQ空间的高清照片,时间一长就变得模糊了? 如今的一些年轻人最喜欢玩的社交软件主要是QQ和微信,实用的功能和口碑使得它们在五花八门的软件中一直成为大家的宠儿,但随着网络科技的不断发 ...

最新文章

  1. 深度前沿:对话管理模型研究最新进展
  2. Linux awk 命令
  3. linux自动挂载windows磁盘
  4. SDL环境初始化测试代码
  5. 网络基础知识(面试基础)
  6. ai的预览模式切换_当AI频繁切换色彩预览模式时 颜色会越变越深 求解?
  7. OC中的@的作用研究
  8. python修改app定位_APP自动化中三大定位工具
  9. 大白菜方式制作win10 PE启动U盘
  10. 魔兽世界服务器修改模型,超简单魔兽世界修改模型 2.43可用 无需登录器
  11. “李记餐厅”微信点餐小程序的设计与实现
  12. 算法篇-union-find并查集
  13. 微信屏蔽网址解决办法:实现被微信屏蔽的网址在微信内正常访问
  14. 熊猫分发_与熊猫度假
  15. 网页打开手机连接到服务器失败,手机服务器无法连接到服务器失败
  16. Word格式处理控件Aspose.Words for .NET水印处理教程——如何添加和删除水印
  17. 2022 开启新的篇章,越努力越幸运
  18. 另一棵树的子树(你一定要会的基础面试题)
  19. Python之人机猜拳游戏
  20. VS上位机开发——曲线显示

热门文章

  1. C# WPD (windows portable devices) 检测WPD设备 获取设备信息
  2. 淘金币抵扣比列设置越多越好吗?
  3. 中国下一代广播电视网(NGB)100问
  4. 用winhex进行GPT磁盘多分区恢复实例——超详细
  5. 一號倉:《漫》--《Documentation》
  6. win7桌面上显示html,Win7如何显示桌面图标?显示桌面图标的方法
  7. ASF之SAR云计算(成果包括RTC GAMMA、InSAR GAMMA、autoRIFT)
  8. 2021电赛延期了?电赛该如何准备?
  9. java大作业的打猎游戏_Java Swing打猎射击游戏源码
  10. java中文首字母_好用的获取中文字符串拼音首字母的方法(亲测)