用ASP.NET讀取QQ相冊

      最近遇到要讀取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
用了兩個DataList 一個用來顯示相冊圖片,一個用來顯示相冊中的圖片。

<%@ Page language="c#" Codebehind="GetPhoto.aspx.cs" AutoEventWireup="false" Inherits="tt.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>
            
<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>

後臺代碼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;

namespace tt
{
    
/// <summary>
    
/// GetPhoto 的摘要說明。
    
/// </summary>

    public 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();
            }

    }


        
Web 窗體設計器生成的代碼

        
//讀取相冊
        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);
        }


        
/// <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 
= "文件保存完成。";
        }

    }


    
/// <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;}
        }

    }

}

發佈了14 篇原創文章 · 獲贊 0 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章