Как читать Long blob из mysql в java? [Дубликат]

Однажды я столкнулся с той же проблемой, когда я не совсем привык к the life in the IoC world. Поле @Autowired одного из моих bean-компонентов является нулевым во время выполнения.

Основная причина заключается в том, что вместо использования автоматически созданного компонента, поддерживаемого контейнером Spring IoC (чье поле @Autowired равно indeed ] правильно введенный), я newing мой собственный экземпляр этого типа бобов и его использование. Конечно, это поле @Autowired равно нулю, потому что Spring не имеет возможности его ввести.

122
задан marioosh 6 June 2011 в 12:36
поделиться

14 ответов

, если вы используете версию Spring версии 3.1 или новее, вы можете указать «производит» в аннотации @RequestMapping. Пример ниже работает для меня из коробки. Нет необходимости в конвертере регистров или что-либо еще, если вы используете веб-mvc (@EnableWebMvc).

@ResponseBody
@RequestMapping(value = "/photo2", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public byte[] testphoto() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
    return IOUtils.toByteArray(in);
}
85
ответ дан Andremoniy 22 August 2018 в 15:04
поделиться
  • 1
    Спасибо, что этот ответ сработал для меня. – Simon 19 July 2015 в 14:47

Весной 4 очень легко вам не нужно вносить какие-либо изменения в фасоль. Отметьте свой тип возврата только @ResponseBody.

Пример: -

@RequestMapping(value = "/image/{id}")
    public @ResponseBody
    byte[] showImage(@PathVariable Integer id) {
                 byte[] b;
        /* Do your logic and return 
               */
        return b;
    }
0
ответ дан Ankit Katiyar 22 August 2018 в 15:04
поделиться
  • 1
    Проблема с этим заключается в том, что тип содержимого установлен неправильно. – ETL 9 December 2014 в 05:03

Вы должны указать тип материала в ответе. Я использую аннотацию @GetMapping с результатами = MediaType.IMAGE_JPEG_VALUE. @RequestMapping будет работать одинаково.

@GetMapping(value="/current/chart",produces = MediaType.IMAGE_JPEG_VALUE)
@ResponseBody
public byte[] getChart() {
    return ...;
}

Без типа носителя трудно догадаться, что на самом деле возвращается (включая любого, кто читает код, браузер и, конечно же, сама Весна). Байт [] просто не определен. Единственный способ определить тип носителя из байта [] - это обнюхивание и угадывание вокруг.

Предоставление типа носителя - это наилучшая практика

0
ответ дан coseos 22 August 2018 в 15:04
поделиться

Это работает для меня весной 4.

@RequestMapping(value = "/image/{id}", method = RequestMethod.GET)
public void findImage(@PathVariable("id") String id, HttpServletResponse resp){

        final Foto anafoto = <find object>
        resp.reset();
        resp.setContentType(MediaType.IMAGE_JPEG_VALUE);
        resp.setContentLength(anafoto.getImage().length);

        final BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(anafoto.getImageInBytes()));

        try {
            FileCopyUtils.copy(in, resp.getOutputStream());
            resp.flushBuffer();
        } catch (final IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

}
3
ответ дан Furetto 22 August 2018 в 15:04
поделиться

С Spring 4.1 и выше вы можете возвращать почти все что угодно (например, картинки, PDF-файлы, документы, банки, молнии и т. д.) довольно просто без каких-либо дополнительных зависимостей. Например, следующим способом может быть способ возврата изображения профиля пользователя из MongoDB GridFS:

@RequestMapping(value = "user/avatar/{userId}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<InputStreamResource> downloadUserAvatarImage(@PathVariable Long userId) {
    GridFSDBFile gridFsFile = fileService.findUserAccountAvatarById(userId);

    return ResponseEntity.ok()
            .contentLength(gridFsFile.getLength())
            .contentType(MediaType.parseMediaType(gridFsFile.getContentType()))
            .body(new InputStreamResource(gridFsFile.getInputStream()));
}

Что нужно отметить:

  • ResponseEntity с InputStreamResource как возвращаемый type
  • Создание стиля построителя ResponseEntity

С помощью этого метода вам не нужно беспокоиться об автоподготовке в HttpServletResponse, бросая IOException или копируя данные потока.

70
ответ дан Jaymes Bearden 22 August 2018 в 15:04
поделиться
  • 1
    Это вызывает следующее исключение: как вы сериализуете MyInputStream ?: Не удалось написать контент: сериализатор не найден для класса com.mongodb.gridfs.GridFSDBFile $ MyInputStream – Nestor Ledon 22 August 2015 в 04:14
  • 2
    Хотя это в основном как пример того, что вы могли бы сделать, Mongo-Java-Driver 3.0.3 с GridFsDBFile.getInputStream () не возвращает анонимный класс MyInputStream. Я бы проверял ваши версии - возможно, обновление? – Jaymes Bearden 24 August 2015 в 17:08
  • 3
    Мне нравится, как этот поток создает файл, а не копирует все это в памяти. См. Также stackoverflow.com/questions/20333394/… – Wim Deblauwe 16 December 2015 в 10:59
  • 4
    элегантное решение – helt 1 February 2016 в 17:56
  • 5
    любой тип ресурса будет работать – Arne Burmeister 28 February 2018 в 13:22

Я думаю, вам, возможно, понадобится служба для хранения файлов и получения этого файла. Подробнее см. здесь

1) Создать хранилище хранения

@Service
public class StorageService {

Logger log = LoggerFactory.getLogger(this.getClass().getName());
private final Path rootLocation = Paths.get("upload-dir");

public void store(MultipartFile file) {
    try {
        Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
    } catch (Exception e) {
        throw new RuntimeException("FAIL!");
    }
}

public Resource loadFile(String filename) {
    try {
        Path file = rootLocation.resolve(filename);
        Resource resource = new UrlResource(file.toUri());
        if (resource.exists() || resource.isReadable()) {
            return resource;
        } else {
            throw new RuntimeException("FAIL!");
        }
    } catch (MalformedURLException e) {
        throw new RuntimeException("FAIL!");
    }
}

public void deleteAll() {
    FileSystemUtils.deleteRecursively(rootLocation.toFile());
}

public void init() {
    try {
        Files.createDirectory(rootLocation);
    } catch (IOException e) {
        throw new RuntimeException("Could not initialize storage!");
    }
}
}

2) Создать Rest Controller для загрузки и получения файла

@Controller
public class UploadController {

@Autowired
StorageService storageService;

List<String> files = new ArrayList<String>();

@PostMapping("/post")
public ResponseEntity<String> handleFileUpload(@RequestParam("file") MultipartFile file) {
    String message = "";
    try {
        storageService.store(file);
        files.add(file.getOriginalFilename());

        message = "You successfully uploaded " + file.getOriginalFilename() + "!";
        return ResponseEntity.status(HttpStatus.OK).body(message);
    } catch (Exception e) {
        message = "FAIL to upload " + file.getOriginalFilename() + "!";
        return      ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(message);
    }
}

@GetMapping("/getallfiles")
public ResponseEntity<List<String>> getListFiles(Model model) {
    List<String> fileNames = files
            .stream().map(fileName -> MvcUriComponentsBuilder
                    .fromMethodName(UploadController.class, "getFile", fileName).build().toString())
            .collect(Collectors.toList());

    return ResponseEntity.ok().body(fileNames);
}

@GetMapping("/files/{filename:.+}")
@ResponseBody
public ResponseEntity<Resource> getFile(@PathVariable String filename) {
    Resource file = storageService.loadFile(filename);
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
            .body(file);
}

}

0
ответ дан Long Nguyen 22 August 2018 в 15:04
поделиться

Не ответы на меня работали, поэтому мне удалось это сделать следующим образом:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("your content type here"));
headers.set("Content-Disposition", "attachment; filename=fileName.jpg");
headers.setContentLength(fileContent.length);
return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);

Настройка заголовка Content-Disposition Мне удалось загрузить файл с помощью аннотации @ResponseBody по моему методу.

2
ответ дан Paulius Matulionis 22 August 2018 в 15:04
поделиться
  • 1
    Интересно, как выглядит ваша подпись метода – Radu Toader 23 October 2015 в 06:58

Используя Spring 3.1.x и 3.2.x, вы должны это сделать:

Метод контроллера:

@RequestMapping("/photo2")
public @ResponseBody byte[] testphoto() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
    return IOUtils.toByteArray(in);
}

И аннотация mvc в сервлет- Файл context.xml:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>image/jpeg</value>
                    <value>image/png</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>
15
ответ дан Peymankh 22 August 2018 в 15:04
поделиться

В дополнение к нескольким ответам здесь несколько указателей (Spring 4.1).

Если у вас нет каких-либо messageconverters, настроенных в вашем WebMvcConfig, если ResponseEntity внутри вашего @ResponseBody работает хорошо .

Если вы это сделаете, то есть у вас есть MappingJackson2HttpMessageConverter, настроенный (например, я), используя ResponseEntity, возвращает org.springframework.http.converter.HttpMessageNotWritableException.

Единственным рабочим решением в этом случае является для обертывания byte[] в @ResponseBody следующим образом:

@RequestMapping(value = "/get/image/{id}", method=RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public @ResponseBody byte[] showImageOnId(@PathVariable("id") String id) {
    byte[] b = whatEverMethodUsedToObtainBytes(id);
    return b;
}

В этом случае нужно правильно настроить messageconverters (и добавить ByteArrayHttpMessageConverer) в свой WebMvcConfig, например:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(mappingJackson2HttpMessageConverter());
    converters.add(byteArrayHttpMessageConverter());
}

@Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(objectMapper);
    return converter;
}

@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
    return arrayHttpMessageConverter;
}

private List<MediaType> getSupportedMediaTypes() {
    List<MediaType> list = new ArrayList<MediaType>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.IMAGE_PNG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    return list;
}
10
ответ дан s.ijpma 22 August 2018 в 15:04
поделиться

В вашем контексте приложения объявите AnnotationMethodHandlerAdapter и registerByteArrayHttpMessageConverter:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
    <util:list>
      <bean id="byteArrayMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
    </util:list>
  </property>
</bean> 

также в методе обработчика задайте соответствующий тип контента для вашего ответа.

6
ответ дан Sid 22 August 2018 в 15:04
поделиться

Помимо регистрации ByteArrayHttpMessageConverter, вы можете использовать ResponseEntity вместо @ResponseBody. Для меня работает следующий код:

@RequestMapping("/photo2")
public ResponseEntity<byte[]> testphoto() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");

    final HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.IMAGE_PNG);

    return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}
56
ответ дан Siggen 22 August 2018 в 15:04
поделиться

Я предпочитаю этот вариант:

private ResourceLoader resourceLoader = new DefaultResourceLoader();

@ResponseBody
@RequestMapping(value = "/{id}",  produces = "image/bmp")
public Resource texture(@PathVariable("id") String id) {
    return resourceLoader.getResource("classpath:images/" + id + ".bmp");
}

Измените тип носителя на то, что у вас есть.

4
ответ дан Tarion 22 August 2018 в 15:04
поделиться
 @RequestMapping(value = "/get-image",method = RequestMethod.GET)
public ResponseEntity<byte[]> getImage() throws IOException {
    RandomAccessFile f = new RandomAccessFile("/home/vivex/apache-tomcat-7.0.59/tmpFiles/1.jpg", "r");
    byte[] b = new byte[(int)f.length()];
    f.readFully(b);
    final HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.IMAGE_PNG);


    return new ResponseEntity<byte[]>(b, headers, HttpStatus.CREATED);



}

Работал для меня.

5
ответ дан Vivek 22 August 2018 в 15:04
поделиться

Так я делаю это с помощью Spring Boot и Guava:

@RequestMapping(value = "/getimage", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public void getImage( HttpServletResponse response ) throws IOException
{
    ByteStreams.copy( getClass().getResourceAsStream( "/preview-image.jpg" ), response.getOutputStream() );
}
1
ответ дан Wim Deblauwe 22 August 2018 в 15:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: