System.IO.Stream в пользу HttpPostedFileBase - PullRequest
2 голосов
/ 14 ноября 2010

У меня есть сайт, на котором я разрешаю пользователям загружать фотографии.В контроллере MVC я принимаю FormCollection в качестве параметра для действия.Затем я читаю первый файл как HttpPostedFileBase.Я использую это для создания миниатюр.Все это прекрасно работает.

В дополнение к тому, что участники могут загружать свои собственные фотографии, я хотел бы использовать System.Net.WebClient для импорта фотографий самостоятельно.

Я пытаюсь обобщить метод, которыйобрабатывает загруженную фотографию (файл), чтобы он мог взять общий объект Stream вместо конкретного HttpPostedFileBase.

Я пытаюсь основать все данные вне Stream, поскольку HttpPostedFileBase имеет свойство InputStreamкоторый содержит поток файла, а WebClient имеет метод OpenRead, который возвращает Stream.

Однако, переходя к Stream через HttpPostedFileBase, похоже, что я теряю ContentType и ContentLength свойств, которые я использую для проверки файла.

Если раньше не работал с двоичным потоком, есть ли способ получить ContentType и ContentLength из потока?Или есть способ создать HttpPostedFileBase объект, используя Stream?

1 Ответ

3 голосов
/ 14 ноября 2010

Вы правы, глядя на это с точки зрения необработанного потока, потому что тогда вы можете создать один метод, который обрабатывает потоки и, следовательно, множество сценариев, из которых они исходят.

В сценарии загрузки файлов поток, который выВы приобретаете на отдельное свойство от типа контента.Иногда магические числа ( здесь также отличный источник ) могут использоваться для определения типа данных по байтам заголовка потока, но это может быть излишним, поскольку данныеуже доступны для вас другими способами (например, заголовок 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;

Используйте свой пользовательский метод в упомянутых вами сценариях, например, так:

Из HttpPostedFileBase экземпляра с именем myPostedFile

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

При использовании WebClient экземпляр с именем webClient1:

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

Вызовите тот же пользовательский метод для любого потока с идентификатором контента, который вы можете анализировать и распознавать.

...