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