最近做UEditor后端接口的时候stream.Length和.Position引发了类型异常
附上代码:
代码语言:javascript复制public Crawler Fetch()
{
if (!IsExternalIPAddress(this.SourceUrl))
{
State = "INVALID_URL";
return this;
}
var request = HttpWebRequest.Create(this.SourceUrl) as HttpWebRequest;
using (var response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
{
State = "Url returns " response.StatusCode ", " response.StatusDescription;
return this;
}
if (response.ContentType.IndexOf("image") == -1)
{
State = "Url is not an image";
return this;
}
ServerUrl = PathFormatter.Format(Path.GetFileName(this.SourceUrl), Config.GetString("catcherPathFormat"));
var savePath = Server.MapPath(ServerUrl);
if (!Directory.Exists(Path.GetDirectoryName(savePath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
}
try
{
this.Stream = response.GetResponseStream();
State = "SUCCESS";
}
catch (Exception e)
{
State = "抓取错误:" e.Message;
}
return this;
}
}原因
当您调用HttpWebResponse.GetResponseStream时,它会返回一个没有任何召回能力的Stream implementation; 换句话说,从HTTP服务器发送的字节将直接发送到此流以供使用。 这与FileStream instance的不同之处在于,如果您想要读取已经通过流消耗的文件的一部分,则可以始终将磁头移回到该位置以从中读取文件(很可能,它在内存中缓冲,但你明白了。 使用HTTP响应,您必须重新发出请求到服务器才能再次获得响应。由于该响应不能保证相同,因此Stream实现上的大多数与位置相关的方法和属性(例如Length,Position,Seek)都会返回给您抛出一个NotSupportedException。 如果您需要在Stream中向后移动,那么您应该创建一个MemoryStream instance并通过CopyTo method将响应Stream复制到MemoryStream中,如下所示:
var request = HttpWebRequest.Create("https://mmbiz.qpic.cn/mmbiz_png/Ljib4So7yuWjvdu96sRKTMicBzS3b7x95rbsnLPYQicM8cHe7WS3e7BOiaiaGXzibebiaYeibyDZB3iaamabJdPNvxdfuGw/0?wx_fmt=png") as HttpWebRequest;
using (var response = request.GetResponse())
{
using (var ms = new MemoryStream())
{
response.GetResponseStream().CopyTo(ms);
Console.WriteLine(ms.Length);
}
}注意
请注意,如果您不使用.NET 4.0或更高版本(引入了Stream类上的CopyTo),那么您可以使用copy the stream manually


