最近做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