【问题】
用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 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已经是跳转到,需要登录的那个页面:
之后的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/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://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 |
而这些值,是从:
获得的:
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信息的