2010-11-14 72 views
2

我有一個網站,我讓會員可以上傳照片。在MVC控制器中,我將FormCollection作爲Action的參數。然後我讀取第一個文件,類型爲HttpPostedFileBase。我用它來生成縮略圖。這一切工作正常。System.IO.Stream贊成HttpPostedFileBase

除了讓會員上傳自己的照片,我想用System.Net.WebClient導入照片自己。

我想概括處理上傳的照片(文件),以便它可以採取一般的流對象,而不是具體的HttpPostedFileBase的方法。

我想因爲HttpPostedFileBase立足事事休流的具有包含該文件流的InputStream屬性和WebClient有一個OpenRead方法,返回流。

但是,通過與流在HttpPostedFileBase,看起來像我丟失ContentTypeContentLength屬性,我用於驗證該文件。

之前沒有使用二進制流,有沒有辦法從Stream中獲取ContentTypeContentLength?或者有沒有辦法使用Stream創建一個HttpPostedFileBase對象?

回答

3

你說得對看它從原始流的角度,因爲你可以創建一個處理流,因此很多情況下他們所來自的一種方法。

在文件上傳的情況下,你獲取流是從內容類型一個單獨的屬性。有時magic numbersalso a great source here)可以被用來檢測由流頭字節的數據類型,但由於該數據是通過其他途徑已經提供給你(這可能是矯枉過正,即Content-Type頭,或.EXT文件擴展名等)。

可以僅僅憑藉閱讀它測量流的字節長度,所以你並不真正需要的Content-Length頭:瀏覽器只是發現它有用事先知道會發生什麼大小的文件。

如果您WebClient的在互聯網上訪問資源URI,它會知道文件擴展名狀http://www.example.com/imagegif,這可以是一個很好的文件類型標識符。

由於文件資料已經提供給你,爲什麼不開多一個論點上的自定義處理方法接受類似的內容類型的字符串標識符:

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; 

使用您自定義的方法在你所提到的,像這樣的場景:

HttpPostedFileBase實例名爲myPostedFile

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

調用相同的自定義方法適用於任何可以匹配內容標識符的流並承認。

+0

我試圖遠離檢查文件擴展名,因爲它很容易僞造。但是,看起來不是另一種方式。謝謝! – 2010-11-14 06:53:45

+0

如果您不相信文件擴展名或它不存在,您可以始終使用幻數。以同樣的方式,您不一定信任瀏覽器標題的內容類型。這裏的文件sigs的示例http://en.wikipedia.org/wiki/List_of_file_signatures – 2010-11-14 06:56:02

+0

我剛剛將這個幻數表添加到答案中 - 它看起來相當全面:http://www.garykessler.net/library/file_sigs html的 – 2010-11-14 07:01:41