System.IO.Stream 支持 HttpPostedFileBase

发布于 2024-10-01 20:02:27 字数 704 浏览 4 评论 0原文

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

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

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

我试图将所有内容都基于 Stream,因为 HttpPostedFileBase 有一个包含文件流的 InputStream 属性,并且 WebClient 有一个 < code>OpenRead 返回 Stream 的方法。

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

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

I have a site where I allow members to upload photos. In the MVC Controller I take the FormCollection as the parameter to the Action. I then read the first file as type HttpPostedFileBase. I use this to generate thumbnails. This all works fine.

In addition to allowing members to upload their own photos, I would like to use the System.Net.WebClient to import photos myself.

I am trying to generalize the method that processes the uploaded photo (file) so that it can take a general Stream object instead of the specific HttpPostedFileBase.

I am trying to base everything off of Stream since the HttpPostedFileBase has an InputStream property that contains the stream of the file and the WebClient has an OpenRead method that returns Stream.

However, by going with Stream over HttpPostedFileBase, it looks like I am loosing ContentType and ContentLength properties which I use for validating the file.

Not having worked with binary stream before, is there a way to get the ContentType and ContentLength from a Stream? Or is there a way to create a HttpPostedFileBase object using the Stream?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

屋檐 2024-10-08 20:02:27

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

在文件上传场景中,您获取的流位于与内容类型不同的属性上。有时幻数 (这里也是一个很好的来源)可用于通过流头字节检测数据类型,但这可能有点矫枉过正,因为您已经可以通过其他方式使用该数据(即 Content-Type 标头或 .ext 文件扩展名等)。

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

如果您的 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));

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

You're right to look at it from a raw stream perspective because then you can create one method that handles streams and therefore many scenarios from which they come.

In the file upload scenario, the stream you're acquiring is on a separate property from the content-type. Sometimes magic numbers (also a great source here) can be used to detect the data type by the stream header bytes but this might be overkill since the data is already available to you through other means (i.e. the Content-Type header, or the .ext file extension, etc).

You can measure the byte length of the stream just by virtue of reading it so you don't really need the Content-Length header: the browser just finds it useful to know what size of file to expect in advance.

If your WebClient is accessing a resource URI on the Internet, it will know the file extension like http://www.example.com/image.gif and that can be a good file type identifier.

Since the file info is already available to you, why not open up one more argument on your custom processing method to accept a content type string identifier like:

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

     } 

}

Some useful filename parsing features are in the IO namespace:

using System.IO;

Use your custom method in the scenarios you mentioned like so:

From an HttpPostedFileBase instance named myPostedFile

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

When using a WebClient instance named webClient1:

var imageFilename = "pic.gif";
var stream = webClient1.DownloadFile("http://www.example.com/images/", imageFilename)
//...
Custom.SavePicture(stream, Path.GetExtension(imageFilename));

Or even when processing a file from disk:

Custom.SavePicture(File.Open(pathToFile), Path.GetExtension(pathToFile));

Call the same custom method for any stream with a content identifer that you can parse and recognize.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文