स्प्रिंग एमवीसी: @ResponseBody में छवि कैसे लौटाएं?


142

मुझे byte[]DB से इमेज डेटा (as ) मिल रहा है । इस छवि को वापस कैसे करें @ResponseBody?

संपादित करें

मैंने इसे विधि पैरामीटर के रूप में @ResponseBodyउपयोग किए बिना किया HttpServletResponse:

@RequestMapping("/photo1")
public void photo(HttpServletResponse response) throws IOException {
    response.setContentType("image/jpeg");
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
    IOUtils.copy(in, response.getOutputStream());
}

@Sid के रूप में @ResponseBodyपंजीकृत org.springframework.http.converter.ByteArrayHttpMessageConverterकनवर्टर के साथ प्रयोग करना मेरे लिए काम नहीं करता है :(।

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

जवाबों:


97

यदि आप 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);
}

78

स्प्रिंग 4.1 और इसके बाद के संस्करण में, आप बहुत अधिक कुछ भी वापस कर सकते हैं (जैसे कि चित्र, पीडीएफ़, दस्तावेज़, जार, ज़िप, आदि) बिना किसी अतिरिक्त निर्भरता के। उदाहरण के लिए, 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()));
}

ध्यान देने योग्य बातें:

  • एक वापसी प्रकार के रूप में InputStreamResource के साथ ResponseEntity

  • ResponseEntity बिल्डर शैली निर्माण

इस पद्धति के साथ आपको HttpServletResponse में ऑटोवायरिंग के बारे में चिंता करने की ज़रूरत नहीं है, एक IOException को फेंकने या स्ट्रीम डेटा को कॉपी करने के लिए।


1
यह निम्न अपवाद फेंकता है, आप कैसे MyInputStream serializing कर रहे हैं ?: नहीं किया जा सका लिखने सामग्री: नहीं serializer वर्ग com.mongodb.gridfs.GridFSDBFile $ MyInputStream के लिए मिला
नेस्टर Ledon

हालांकि यह मुख्य रूप से एक उदाहरण के रूप में कि आप संभवतः क्या कर सकते हैं, GridFsDBFile.getInputStream () के साथ Mongo-Java-Driver-3.0 3.0 MyInputStream नामक एक अनाम वर्ग वापस नहीं करता है। मैं आपके संस्करणों की जाँच करूँगा - शायद अद्यतन?
जेम्स बेयरडेन

4
मुझे पसंद है कि यह पूरी मेमोरी में कॉपी करने के बजाय फाइल को कैसे स्ट्रीम करता है। यह भी देखें stackoverflow.com/questions/20333394/…
Wim Deblauwe

60

पंजीकरण के अलावा 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);
}

16

स्प्रिंग 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);
}

और सर्वलेट-प्रसंग। Xml फ़ाइल में mvc एनोटेशन:

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

13

कुछ जवाबों के अलावा यहां कुछ संकेत (स्प्रिंग 4.1) हैं।

आप अपने 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;
}

इस मामले 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;
}

6

अपने आवेदन के संदर्भ में एक एनोटेशनमेथोडहैंडलर एडेप्टर और रजिस्टरबाइटएयर्रेहेटपेसमैसेजऑनर्टर को घोषित करें:

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

हैंडलर विधि में भी आपकी प्रतिक्रिया के लिए उपयुक्त सामग्री प्रकार सेट करें।


@jsinghfoss शीर्ष उत्तर को देखें।
पयमनख

6
 @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

मैं इसे पूर्ववर्ती करता हूं:

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

मीडिया का प्रकार बदलें जो आपके पास कभी भी छवि प्रारूप में हो।


1
अच्छा कॉल करें ResourceLoader, लेकिन आपके उदाहरण के रूप में बाहरी इनपुट से पथनाम का निर्माण करना एक बुरा विचार है: cwe.mitre.org/data/definitions/22.html
qerub

3

यह मेरे लिए स्प्रिंग 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();
        }

}

2

मेरे लिए काम किए गए उत्तरों में से कोई भी ऐसा नहीं है, इसलिए मैं इसे इस तरह करने में कामयाब रहा:

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

आपको प्रतिक्रिया में मीडिया प्रकार निर्दिष्ट करना चाहिए। मैं उत्पादन के साथ @ MediaType.IMAGE_JPEG_VALUE @GetMapping एनोटेशन का उपयोग कर रहा हूं। @RequestMapping ही काम करेगा।

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

मीडिया प्रकार के बिना, यह अनुमान लगाना कठिन है कि वास्तव में क्या लौटाया जाता है (इसमें कोई भी जो कोड, ब्राउज़र और निश्चित रूप से स्प्रिंग स्वयं पढ़ता है) शामिल है। एक बाइट [] अभी विशिष्ट नहीं है। बाइट से मीडिया प्रकार को निर्धारित करने का एकमात्र तरीका [] सूँघ रहा है और चारों ओर अनुमान लगा रहा है।

मीडिया प्रकार प्रदान करना केवल सर्वोत्तम अभ्यास है


यह मेरे लिए स्प्रिंग बूट 2.x में काम करता है। साझा करने के लिए धन्यवाद।
अटाकोमेशियन

1

यह है कि मैं इसे स्प्रिंग बूट और अमरूद के साथ कैसे करता हूं:

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

0

वसंत 4 में यह बहुत आसान है, आपको सेम में कोई भी बदलाव करने की आवश्यकता नहीं है। केवल अपने रिटर्न प्रकार को @ResponseBody पर चिह्नित करें।

उदाहरण:-

@RequestMapping(value = "/image/{id}")
    public @ResponseBody
    byte[] showImage(@PathVariable Integer id) {
                 byte[] b;
        /* Do your logic and return 
               */
        return b;
    }

1
समस्या मुझे इसके साथ मिलती है, सामग्री प्रकार ठीक से सेट नहीं किया गया है।
ETL

0

मुझे लगता है कि आपको फ़ाइल अपलोड को संग्रहीत करने और उस फ़ाइल को प्राप्त करने के लिए एक सेवा की आवश्यकता हो सकती है। अधिक विवरण यहां से देखें

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) अपलोड करने और फाइल प्राप्त करने के लिए रेस्ट कंट्रोलर बनाएं

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

}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.