Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException
вообще.
См. также: A хороший список лучших практик
Я бы добавил, очень важно, хорошо использовать модификатор final
. Использование "окончательной" модификатор, когда это применимо в Java
Сводка:
final
для обеспечения хорошей инициализации. @NotNull
и @Nullable
if("knownObject".equals(unknownObject)
valueOf()
поверх toString (). StringUtils
StringUtils.isEmpty(null)
. На самом деле это действительно просто. HttpPostedFileBase - это абстрактный класс, используемый исключительно с целью получения. Он использовался так, что некоторые вещи в закрытом классе HttpPostedFile были бы издевательскими.
Однако в реальной жизни HttpPostedFile - это то, что у вас есть для обработки размещенных файлов, и чтобы быть последовательным, был создан HttpPostedFileWrapper. Этот класс обеспечивает реализацию для HttpPostedFileBase путем переноса HttpPostedFile.
Итак, HttpPostedFileBase - это унифицированная абстракция, HttpPostedFile - это класс, представляющий опубликованные файлы, а HttpPostedFileWrapper - это реализация HttpPostedFileBase, которая обертывает HttpPostedFile. Реализация свойства ContentType для HttpPostedFileWrapper считывает тип содержимого из подкласса HttpPostedFile.
EDIT: какое-то объяснение
ASP.NET MVC получил файл, а где-то в глубине ниже он создал экземпляр HttpPostedFile, так как это работает с .NET Framework 1.0. Определение HttpPostedFile выглядит следующим образом:
public sealed class HttpPostedFile
, который в основном означает, что он не может быть унаследован и не может быть посмеялся за модульное тестирование.
Чтобы устранить эту проблему ASP. NET MVC разработчики создали макет абстракции - HttpPostedFileBase, который определяется следующим образом:
public abstract class HttpPostedFileBase
Итак, теперь вы можете определить свои действия MVC, чтобы они принимали HttpPostedFileBase, а не un-mockable HttpPostedFile:
[HttpPost]
public ActionResult PostFile(HttpPostedFileBase file)
{
// some logic here...
}
Проблема в том, что где-то глубоко внизу, единственный способ представить опубликованный файл - это хороший старый жесткий HttpPostedFile. Поэтому, чтобы поддержать эту абстракцию, разработчики MVC создали декоратор под названием HttpPostedFileWrapper, который выглядит примерно так:
public class HttpPostedFileWrapper : HttpPostedFileBase
{
private HttpPostedFile _httpPostedFile;
public HttpPostedFileWrapper(HttpPostedFile httpPostedFile) {
_httpPostedFile = httpPostedFile;
}
public string ContentType { get { return _httpPostedFile.ContentType; } }
// implementation of other HttpPostedFileBase members
}
Итак, теперь HttpPostedFileWrapper - это то, что вы на самом деле получаете при выполнении реального HTTP-запроса POST с опубликованным файлом. Благодаря полиморфизму вы можете передать экземпляр производного класса - HttpPostedFileWrapper - к методу, принимающему базовый класс - HttpPostedFileBase.
Все это время вы можете создать свою собственную макетную реализацию, которая, например, будет выглядеть как видео файл публикуется. Вы сделали бы это так
public class MockPostedVideoFile : HttpPostedFileBase
{
public string ContentType { get { return "video/mp4"; } }
// rest of implementation here
}
ДРУГОЕ ИЗМЕНЕНИЕ: Фактическое создание HttpPostedFile обрабатывается System.Web для вас. Связывание ASP.NET MVC довольно разумно в отношении данных о форме. Он автоматически обнаруживает, что определенные значения сообщений фактически являются байтами файла, поэтому для правильного их представления он может использовать что-то старое из фреймворка System.Web для создания экземпляра HttpPostedFile.
Главное, - вам не нужно беспокоиться об этом. Здесь есть много вещей, и нам действительно нужно быть благодарными команде ASP.NET MVC за то, что они абстрагировали все эти низкоуровневые вещи.
Единственное место, где вам нужно беспокоиться об этом - это модульное тестирование. В своем тесте вы можете просто вызвать свое действие с помощью макетной реализации, например:
myController.PostFile(new MockPostedVideoFile())