最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【基本解决】C#中如何获取给定URL的网络上的图片,并在PictureBox上显示出来,并且支持带验证的Cookie信息的

C# crifan 5384浏览 0评论

【问题】
用C#给WLW写插件,其中用到显示图片的功能。
之前已有代码,可以实现图片的(预览)显示了:

WindowsLive.Writer.Api.PluginHttpRequest http = new WindowsLive.Writer.Api.PluginHttpRequest(url);
http.AllowAutoRedirect = true;
http.CacheLevel = WindowsLive.Writer.Api.HttpRequestCacheLevel.BypassCache;
using (System.IO.Stream imageStream = http.GetResponse())
{
    theImage = Image.FromStream(imageStream);
}

只是刚发现,如果对应的图片,比如:

http://storage.live.com/items/9A8B8BF501A38A36!955?filename=_…Net%20-%20testName.jpg

是skydrive用户没有设置为public,需要登录才可以访问的,即需要对应权限才能访问的话,那么上面代码中:

theImage = Image.FromStream(imageStream);

在运行时候会出错。

然后去网页中分析过程发现,服务器返回的是Access Denied,表示木有权限,所以后面送给Image.FromStream的imageStream,其实不是有效数据,

而是返回的调转后的登陆页面的html。

所以,此处就是需要,如果实现带cookie验证信息的,从url获取网上图片,并在PictureBox中显示出来。

【解决过程】

1.对于如何从url获得图片并显示,网上找了一下,发现这里:

http://blog.csdn.net/successhen/article/details/4208238

解释的很清晰,先是用http去request,

然后获得stream后,用Image保存,再赋值给picturebox去显示。

而此处,我自己已有对应代码获得对应的cookie,所以剩下的就是去写代码了。

2.写好了对应的代码:

req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
//req.AllowAutoRedirect = true;
req.AllowAutoRedirect = false;
req.Accept = "*/*";
req.Headers["Accept-Language"] = gAcceptLanguage;
req.KeepAlive = true;
req.UserAgent = gUserAgent;
req.Headers["Accept-Encoding"] = "gzip, deflate";
req.AutomaticDecompression = DecompressionMethods.GZip;
req.Proxy = null;
if (skydriveCookies != null)
{
    req.CookieContainer = new CookieContainer();
    req.CookieContainer.PerDomainCapacity = 40; // following will exceed max default 20 cookie per domain
    req.CookieContainer.Add(skydriveCookies);
}

但是还是不能获取图片,对应的response返回的是:

A。如果是 req.AllowAutoRedirect = false;

返回的是

{Connection: Keep-Alive

Proxy-Connection: Keep-Alive

X-MSNSERVER: BY2____4011416

X-ClientErrorCode: AccessDenied

Content-Length: 0

Date: Fri, 09 Mar 2012 04:55:24 GMT

Location: https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1331268924&rver=6.1.6206.0&wp=MBI&wreply=http:%2F%2Fstorage.live.com%2Fstorageservice%2Fpassport%2Fauth.aspx%3Fsru%3Dhttp:%252f%252fstorage.live.com%252fitems%252f9A8B8BF501A38A36!955&lc=1033&id=63539

P3P: CP="BUS CUR CONo FIN IVDo ONL OUR PHY SAMo TELo"

Via: 1.1 SC-SZ-06

WWW-Authenticate: WLID1.0 realm="WindowsLive", fault="BadContextToken", policy="MBI_SSL", ver="6.1.6206.0", target="storage.live.com"

}

意思是,没有权限访问。

B。如果是req.AllowAutoRedirect = true;

返回的是:

{X-XSS-Protection: 0

X-Content-Type-Options: nosniff

Content-Length: 18219

Cache-Control: max-age=0

Content-Type: text/html; charset=utf-8

Expires: Fri, 09 Mar 2012 04:39:04 GMT

P3P: CP="DSP CUR OTPi IND OTRi ONL FIN"

Set-Cookie: MSPRequ=lt=1331268004&co=1&id=63539; path=/;version=1,MSPOK=$uuid-d6399acc-980b-46c2-91da-465c8ee9b544; path=/;version=1

Server: Microsoft-IIS/7.5

X-Frame-Options: deny

PPServer: PPV: 30 H: BAYIDSLGN1M60 V: 0

Date: Fri, 09 Mar 2012 04:40:03 GMT

Connection: close

}

看起来没有权限错误,但是实际上是由于允许redirect,此处的response已经是跳转到,需要登录的那个页面:

https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1331268924&rver=6.1.6206.0&wp=MBI&wreply=http:%2F%2Fstorage.live.com%2Fstorageservice%2Fpassport%2Fauth.aspx%3Fsru%3Dhttp:%252f%252fstorage.live.com%252fitems%252f9A8B8BF501A38A36!955&lc=1033&id=63539

之后的response了,所以也还是没能正常获取图片。

3.类似的BadContextToken的错误,之前就遇到,当时的解决办法是,

确保对应的cookie的domain,是符合当前的url,因此,也去做对应的处理,把当前已有的cookies,

全部拷贝一份,然后每个domain都设置为当前url:

http://storage.live.com/items/9A8B8BF501A38A36!955?filename=_…Net%20-%20testName.jpg

所对应的domain:storage.live.com

试的结果,还是AccessDenied。

4.去用Chrome和IE9分析,登录skydrive后,直接浏览器输入该url,结果分析到的现象,好像也是很平常的,没啥特殊的,就是访问此url,

然后添加对应的cookie而已,然后就可以获得图片数据了。

5.后来,尝试了,在退出登录skydrive后,再输入对应的url,

结果跳转到那个login.live.com/login.srf需要登录,然后输入用户名和密码登录后,

分析到的结果是,其会先去:

http://storage.live.com/storageservice/passport/auth.aspx?sru=http:%2f%2fstorage.live.com%2fitems%2f9A8B8BF501A38A36!955

做认证,然后认证成功后,才返回到:

http://storage.live.com/items/9A8B8BF501A38A36!955

的地址,返回对应的图片数据。

所以,看来应该是这个原因了,因为前面模拟登陆skydrive的时候,是没有去登陆到storage.live.com/storageservice做认证的,

因为用登陆后的cookie,已经足够可以访问文件夹,列出文件,创建文件夹,上传文件等操作了。

看来此处需要访问对应的非共享的图片,还是需要去storageservice认证的。

去认证了,结果返回错误:

[System.Net.WebException] {"The remote server returned an error: (400) Bad Request."} System.Net.WebException

{Connection: Keep-Alive

Proxy-Connection: Keep-Alive

X-MSNSERVER: BY2____4011907

Content-Length: 26

Date: Fri, 09 Mar 2012 05:37:06 GMT

P3P: CP="BUS CUR CONo FIN IVDo ONL OUR PHY SAMo TELo"

Via: 1.1 SC-SZ-06}

6.后来又去重新分析skydrive登陆的全过程,看看到底是如何去storage.live.com/storageservice认证的,

然后分析的结果是,又是和之前那个及其繁琐和复杂的过程:

要跳转很多步骤:

从访问:

https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1331271906&rver=6.1.6206.0&wp=MBI_SSL&wreply=https%3a%2f%2fauth.bay.livefilestore.com%2fstorageservice%2fpassport%2flogin.aspx%3fcid%3d-7310595685695124938%26cru%3dhttps%253a%252f%252fskydrive.live.com%252fCookieToss%253fv%253d3&lc=1033&id=250915

获得的下面的地址:

https://auth.bay.livefilestore.com/storageservice/passport/login.aspx?cid=-7310595685695124938&cru=https%3a%2f%2fskydrive.live.com%2fCookieToss%3fv%3d3&wa=wsignin1.0

然后去认证的。

而为了做此认证,需要NAP,ANON,t的Post data:

NAP=V%253D1.9%2526E%253Dc08%2526C%253Df_hLEm1QP92JLUAISJ_BvwvP8MPQj5146CYaaeFzo4j41l-hm2dUYw%2526W%253D1&ANON=A%253DDE389D4D076BF47BCAE4DC05FFFFFFFF%2526E%253Dc62%2526W%253D1&t=EgBnAQMAAAAEgAAACoAA4bEU3UDeErqS3jnY2DbMmh94hms6TTgQUKG1cmoGhXwDHXW6nJM%2B%2BnCvaBQOEjPUPC9lgr%2FfzwANxSiitbAtQU1rVEfwq8gZ25kMpUNIjCy%2FbLZdFzmosC8%2F%2FseEyEIe5%2FdXI9cklRdUhiDceM%2F6rmlH%2BtNdQONDzh5ydZa2ikDWAFwA1gD9vwYA7Vazl%2BCYWU%2FgmFlPI9QDAAoQIAAAFwBjcmlmYW4yMDAzQGhvdG1haWwuY29tAE8AABZjcmlmYW4yMDAzQGhvdG1haWwuY29tAAAACkNOAAYyMTM1OTIAAAZlCAQCAAB3F21AAARDAAR0aWFuAAR3YW5nBMgAAUkAAAAAAAAAAAAAAaOKNpqLi%2FUAAOKYWU%2FiDWxPAAAAAAAAAAAAAAAADgA1OC4yNDAuMjM2LjE5AAUAAAAAAAAAAAAAAAABBAABAAABAAABAAAAAAAAAAA%3D

而这些值,是从:

https://login.live.com/ppsecure/post.srf?wa=wsignin1.0&rpsnv=11&ct=1331271895&rver=6.1.6206.0&wp=MBI_SSL_SHARED&wreply=https:%2F%2Fskydrive.live.com%2F&lc=1033&id=250206&mkt=en-US&cbcxt=sky&bk=1331271895

获得的:

Direction Key Value Expires Domain Path Secure HTTP only

Received NAP V=1.9&E=c08&C=f_hLEm1QP92JLUAISJ_BvwvP8MPQj5146CYaaeFzo4j41l-hm2dUYw&W=1 At end of session .live.com / No No

Received ANON A=DE389D4D076BF47BCAE4DC05FFFFFFFF&E=c62&W=1 At end of session .live.com / No No

总之,为了可以访问非共享出来的图片,还是需要很多个繁琐的工作的,虽然这些工作之前都已经做完了,但是代码已经被删掉了,可以在之前的版本的项目中找到,但是还是很费事。

决定暂时不支持登陆模式下查看/预览非共享的图片。

等以后有时间再添加这个次要的功能。

【总结】

上面说了一堆,其实只是针对skydrive中想要访问非共享图片的复杂过程。

对于一般普通的url,访问对应的图片,其实参考前面那人的解释,早就实现了对应代码了:

【完整的代码:访问普通url图片地址,获得对应的Image并显示(带Cookie,带压缩,带自动缩放图片)】

HttpWebRequest req;
HttpWebResponse resp;

req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "GET";
req.AllowAutoRedirect = true;
req.Accept = "*/*";
//req.Headers["Accept-Language"] = gAcceptLanguage;
req.KeepAlive = true;
//req.UserAgent = gUserAgent;

if (useGzip)
{
    req.Headers["Accept-Encoding"] = "gzip, deflate";
    req.AutomaticDecompression = DecompressionMethods.GZip;
}

req.Proxy = null;

//skydriveCookies is previously got cookies
if (skydriveCookies != null)
{
    req.CookieContainer = new CookieContainer();
    //req.CookieContainer.PerDomainCapacity = 40; // following will exceed max default 20 cookie per domain
    req.CookieContainer.Add(skydriveCookies);
}

//refer: http://blog.csdn.net/successhen/article/details/4208238
resp = (HttpWebResponse)req.GetResponse();
Stream imgStream = resp.GetResponseStream(); // got image stream
theImage = Image.FromStream(imgStream); // generate image from stream

// refer: http://my.oschina.net/duluo180/blog/8131
pcbPic.Image = theImage;
// refer: http://wenwen.soso.com/z/q163706867.htm
pcbPic.Dock = DockStyle.Fill; //auto fill
pcbPic.SizeMode = PictureBoxSizeMode.Zoom;

转载请注明:在路上 » 【基本解决】C#中如何获取给定URL的网络上的图片,并在PictureBox上显示出来,并且支持带验证的Cookie信息的

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

网友最新评论 (2)

  1. 你的主题还要改改啊,像这个页面,在chrome下看,好多引用框都撑破了,很难看。
    ZXR12年前 (2012-03-27)回复
    • 恩,是存在这个问题的,有空再弄这个相对次要的问题,因为最近还有其他更多的主要问题,待偶解决,呵呵。
      crifan12年前 (2012-03-27)回复
87 queries in 0.170 seconds, using 22.15MB memory