FileSystemResource возвращается с типом содержимого json

У меня есть следующий метод Spring MVC, который возвращает файл:

@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public FileSystemResource getFiles(@PathVariable String fileName){

    String path="/home/marios/Desktop/";

    return new FileSystemResource(path+fileName);

}

Я ожидаю, что ResourceHttpMessageConverter создаст соответствующий ответ с типом потока октетов в соответствии с его документацией:

Если JAF недоступен, используется application/octet-stream.

Однако, хотя я правильно получаю файл без проблем, в результате получается Content-Type: application/json;charset=UTF-8

Можете ли вы сказать мне, почему это происходит?

(Я использую Spring версии 4.1.4. Я не установил явно никаких конвертеров сообщений, и я знаю, что Spring по умолчанию загружает среди прочих ResourceHttpMessageConverter, а также MappingJackson2HttpMessageConverter, потому что у меня есть jackson 2 в моем classpath, потому что у меня есть другой mvc методы, которые возвращают JSON.

Также, если я использую HttpEntity<FileSystemResource> и установите вручную тип содержимого или укажите его с помощью produces = MediaType.APPLICATION_OCTET_STREAM это работает отлично.

Также обратите внимание, что в моем запросе я не указываю какие-либо типы принимаемого контента и предпочитаю не полагаться на моих клиентов)

2 ответа

Решение

Я закончил отлаживать все это, и я обнаружил, что AbstractJackson2HttpMessageConverter имеет canWrite реализация, которая возвращает истину в случае FileSystemResource потому что он просто проверяет, является ли класс сериализуемым, и устанавливает тип носителя, который является нулевым, поскольку я не указываю ничего, что в этом случае должно поддерживаться им.

В результате он заканчивает тем, что помещает типы контента json в список типов воспроизводимых носителей. Конечно ResourceHttpMessageConverter.canWrite реализация также, естественно, возвращает истину, но ResourceHttpMessageConverter не возвращает какие-либо производимые типы носителей.

Когда приходит время написать фактический ответ, из write Реализация метода, запись ResourceHttpMessageConverter запускается первым из-за того, что ResourceHttpMessageConverter первым в списке доступных конвертеров (если MappingJackson2HttpMessageConverter был бы первым, попытался бы позвонить write так как его canWrite возвращает true и выдает исключение), и, поскольку уже был задан производимый тип контента, он по умолчанию не запускает ResourceHttpMessageConverter.getDefaultContentType это установит правильный тип контента.

Если я удалю json converter, все будет работать нормально, но, к сожалению, ни один из моих методов json не будет работать. Следовательно, указание типа содержимого - единственный способ избавиться от возвращенного типа содержимого json.

Для тех, кто все еще ищет фрагмент кода:

Вам следует завернуть FileSystemResource в ResponseEntity<> Затем определите тип содержимого вашего изображения и добавьте его в ResponseEntity как заголовок.

Вот пример:

      @GetMapping("/image")
public @ResponseBody ResponseEntity<FileSystemResource> getImage() throws IOException {

    File file = /* load your image file from anywhere */;
    if (!file.exists()) {
        //TODO: throw 404
    }

    FileSystemResource resource = new FileSystemResource(file);
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(/* determine your image's media type or just set it as a constant using MediaType.<value> */);
    headers.setContentLength(resource.contentLength());

    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
Другие вопросы по тегам