asp.net-mvc - System.IO.Stream 支持 HttpPostedFileBase

标签 asp.net-mvc webclient httppostedfilebase

我有一个允许成员(member)上传照片的网站。在 MVC Controller 中,我将 FormCollection 作为 Action 的参数。然后,我将第一个文件读取为 HttpPostedFileBase 类型。我用它来生成缩略图。这一切都运行良好。

除了允许成员(member)上传自己的照片外,我还想使用System.Net.WebClient自己导入照片。

我试图概括处理上传照片(文件)的方法,以便它可以采用通用 Stream 对象而不是特定的 HttpPostedFileBase

我试图将所有内容都建立在 Stream 的基础上,因为 HttpPostedFileBase 有一个 InputStream 属性,其中包含文件流和 WebClient有一个返回 Stream 的 OpenRead 方法。

但是,通过在 HttpPostedFileBase 上使用 Stream,看起来我丢失了用于验证文件的 ContentTypeContentLength 属性.

之前没有使用过二进制流,有没有办法从流中获取 ContentTypeContentLength ?或者有没有办法使用 Stream 创建 HttpPostedFileBase 对象?

最佳答案

您从原始流的角度看待它是正确的,因为这样您就可以创建一种方法来处理流,从而处理它们来自的许多场景。

在文件上传场景中,您获取的流位于与内容类型不同的属性上。有时magic numbers ( also a great source here ) 可用于通过流 header 字节检测数据类型,但这可能有点过大,因为数据已经可以通过其他方式(即 Content-Type header 或 .ext 文件扩展名等)提供给您)。

您可以仅通过读取流来测量流的字节长度,因此您实际上不需要 Content-Length header :浏览器只是发现提前知道预期文件的大小很有用。

如果您的 WebClient 正在访问 Internet 上的资源 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;

在您提到的场景中使用您的自定义方法,如下所示:

来自名为 myPostedFileHttpPostedFileBase 实例

 Custom.SavePicture(myPostedFile.InputStream, myPostedFile.ContentType);

使用名为 webClient1WebClient 实例时:

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));

使用您可以解析和识别的内容标识符为任何流调用相同的自定义方法。

关于asp.net-mvc - System.IO.Stream 支持 HttpPostedFileBase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4176349/

相关文章:

jquery - ASP.NET MVC 远程验证钩子(Hook)方法

javascript - 在 javascript 函数中使用 @Html.Raw

c# - 下载字符串和特殊字符

silverlight - 在 Silverlight 中使用安全关键构造函数子类化透明类型的安全规则

c# - 如何限制文件上传的大小但显示有意义的响应?

c# - SetCookie 似乎无法正常工作

c# - 如何使用权限而不是角色在 asp.net Identity 中授权用户?

c# - 如何在C#中使用TPL实现异步文件下载

asp.net-mvc - 将图像 URL 转换为 HttpPostedFileBase

c# - HttpPostedFileBase 与 HttpPostedFileWrapper 的关系