我有一个网站,我允许会员上传照片。在MVC控制器中,我将FormCollection
作为Action的参数。然后我将第一个文件读作类型HttpPostedFileBase
。我用它来生成缩略图。一切正常。
除了允许会员上传自己的照片外,我还想使用System.Net.WebClient
自行导入照片。
我正在尝试概括处理上传的照片(文件)的方法,以便它可以采用一般的Stream对象而不是特定的HttpPostedFileBase
。
我试图将所有内容从Stream中删除,因为HttpPostedFileBase
具有包含文件流的InputStream
属性,而WebClient
具有OpenRead
方法返回Stream。
但是,通过使用Stream HttpPostedFileBase
,看起来我正在丢失用于验证文件的ContentType
和ContentLength
属性。
以前没有使用二进制流,有没有办法从流中获取ContentType
和ContentLength
?或者有没有办法使用Stream创建HttpPostedFileBase
对象?
答案 0 :(得分:3)
您从原始流的角度来看是正确的,因为您可以创建一个处理流的方法,因此可以创建许多方案。
在文件上传方案中,您要获取的流与内容类型位于不同的属性中。有时magic numbers(also a great source here)可用于通过流头字节检测数据类型,但这可能是过度的,因为数据已经通过其他方式(即Content-Type头,或.ext文件扩展名等。)
您可以通过读取来测量流的字节长度,这样您就不需要Content-Length标头:浏览器只是发现提前了解文件大小有用。
如果您的 WebClient 正在访问互联网上的资源URI,它会知道文件扩展名,如http://www.example.com/image。 gif ,这可能是一个不错的文件类型标识符。
由于您已经可以使用文件信息,为什么不在自定义处理方法上再打开一个参数来接受内容类型字符串标识符,如:
public static class Custom {
// Works with a stream from any source and a content type string indentifier.
static public void SavePicture(Stream inStream, string contentIdentifer) {
// Parse and recognize contentIdentifer to know the kind of file.
// Read the bytes of the file in the stream (while counting them).
// Write the bytes to wherever the destination is (e.g. disk)
// Example:
long totalBytesSeen = 0L;
byte[] bytes = new byte[1024]; //1K buffer to store bytes.
// Read one chunk of bytes at a time.
do
{
int num = inStream.Read(bytes, 0, 1024); // read up to 1024 bytes
// No bytes read means end of file.
if (num == 0)
break; // good bye
totalBytesSeen += num; //Actual length is accumulating.
/* Can check for "magic number" here, while reading this stream
* in the case the file extension or content-type cannot be trusted.
*/
/* Write logic here to write the byte buffer to
* disk or do what you want with them.
*/
} while (true);
}
}
一些有用的文件名解析功能在IO命名空间中:
using System.IO;
在您提到的场景中使用自定义方法,如下所示:
来自名为myPostedFile
的 HttpPostedFileBase 实例
Custom.SavePicture(myPostedFile.InputStream, myPostedFile.ContentType);
使用名为webClient1
的 WebClient 实例时:
var imageFilename = "pic.gif";
var stream = webClient1.DownloadFile("http://www.example.com/images/", imageFilename)
//...
Custom.SavePicture(stream, Path.GetExtension(imageFilename));
甚至从磁盘处理文件时:
Custom.SavePicture(File.Open(pathToFile), Path.GetExtension(pathToFile));
为具有您可以解析和识别的内容标识符的任何流调用相同的自定义方法。