web-dev-qa-db-fra.com

Comment envoyer une image du service Web au printemps

Je rencontre un problème lors de l'envoi d'une image à l'aide du service Web Spring.

J'ai écrit le contrôleur comme ci-dessous

@Controller
public class WebService {

    @RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
    public @ResponseBody byte[] getImage() {
        try {
            InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write( bufferedImage  , "jpg", byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

@ResponseBody convertit la réponse en JSON.

J'utilise RestClient pour tester le service Web.

Mais quand je frappe avec http://localhost:8080/my-war-name/rest/image URL.

Header 
Accept=image/jpg

Je suis confronté à l'erreur suivante sur RestClient

La conversion du corps de réponse en chaîne à l'aide du codage windows-1252 a échoué. Corps de réponse non défini!

Quand j'utilise les navigateurs Chrome et Firefox

Les en-têtes ne sont pas ajoutés alors une erreur était attendue (Merci de me guider à ce sujet)

 État HTTP 405 - Méthode de requête 'GET' non prise en charge 
 
 Type Rapport de statut 
 
 Message Méthode de requête 'GET' non prise en charge 
 
 description La méthode HTTP spécifiée n'est pas autorisée pour la ressource demandée (la méthode Request 'GET' n'est pas prise en charge). 
.

J'ai aussi fait face à l'erreur ci-dessous une fois

La ressource identifiée par cette demande est uniquement capable de générer des réponses avec des caractéristiques non acceptables selon la requête "accepter" en-têtes ()

J'ai suivi http://krams915.blogspot.com/2011/02/spring-3-rest-web-service-provider-and.html tutorial.

Mon besoin est d'envoyer une image au format octet à Android Client.

10
Ketan

En plus de répondre fournie par soulcheck. Spring a ajouté produit property à @RequestMapping annotation. Par conséquent, la solution est plus facile maintenant:

@RequestMapping(value = "/image", method = RequestMethod.GET, produces = "image/jpg")
public @ResponseBody byte[] getFile()  {
    try {
        // Retrieve image from the classpath.
        InputStream is = this.getClass().getResourceAsStream("/test.jpg"); 

        // Prepare buffered image.
        BufferedImage img = ImageIO.read(is);

        // Create a byte array output stream.
        ByteArrayOutputStream bao = new ByteArrayOutputStream();

        // Write to output stream
        ImageIO.write(img, "jpg", bao);

        return bao.toByteArray();
    } catch (IOException e) {
        logger.error(e);
        throw new RuntimeException(e);
    }
}
18
Taras Matyashovskyy

La réponse de #soulcheck est partiellement correcte. La configuration ne fonctionnera pas dans la dernière version de Spring car elle se heurterait à l'élément mvc-annotation. Essayez la configuration ci-dessous.

<mvc:annotation-driven>
  <mvc:message-converters register-defaults="true">
    <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
  </mvc:message-converters>
</mvc:annotation-driven>

Une fois que vous avez la configuration ci-dessus dans votre fichier de configuration. Le code ci-dessous fonctionnera:

@RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public @ResponseBody BufferedImage getImage() {
    try {
        InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
        return ImageIO.read(inputStream);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
3
jsf

Voir cet article sur l’excellent site Web baeldung.com .

Vous pouvez utiliser le code suivant dans votre contrôleur à ressort:

@RequestMapping(value = "/rest/getImgAsBytes/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImgAsBytes(@PathVariable("id") final Long id, final HttpServletResponse response) {
    HttpHeaders headers = new HttpHeaders();
    headers.setCacheControl(CacheControl.noCache().getHeaderValue());
    response.setContentType(MediaType.IMAGE_JPEG_VALUE);

    try (InputStream in = imageService.getImageById(id);) { // Spring service call
        if (in != null) {
            byte[] media = IOUtils.toByteArray(in);
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK);
            return responseEntity;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new ResponseEntity<>(null, headers, HttpStatus.NOT_FOUND);
}

Remarques: IOUtils provient de la bibliothèque Apache Common-io. J'utilise un service Spring pour récupérer des blobs img/pdf à partir d'une base de données.

Gestion similaire pour les fichiers pdf, sauf que vous devez utiliser MediaType.APPLICATION_PDF_VALUE dans le type de contenu. Et vous pouvez vous référer au fichier image ou au fichier pdf à partir d’une page html:

<html>
  <head>
  </head>
  <body>
    <img src="https://localhost/rest/getImgDetectionAsBytes/img-id.jpg" />
    <br/>
    <a href="https://localhost/rest/getPdfBatchAsBytes/pdf-id.pdf">Download pdf</a>
  </body>
</html>

... ou vous pouvez appeler la méthode de service Web directement depuis votre navigateur.

2
razvanone

Abandonnez la conversion en json et envoyez le tableau d'octets tel quel.

Le seul inconvénient est qu'il envoie le type de contenu application/octet-stream par défaut.

Si cela ne vous convient pas, vous pouvez utiliser BufferedImageHttpMessageConverter qui peut envoyer tout type d'image pris en charge par les lecteurs d'images enregistrés.

Ensuite, vous pouvez changer votre méthode pour:

@RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public @ResponseBody BufferedImage getImage() {
    try {
        InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
        return ImageIO.read(inputStream);


    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

en ayant :

 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="order" value="1"/>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
        </list>
    </property>
</bean>

dans votre config de printemps.

1
soulcheck

Voici la méthode que j'ai écrite pour cela.

J'avais besoin d'afficher l'image en ligne sur une page et de la télécharger éventuellement sur le client. Je prends donc un paramètre facultatif pour définir l'en-tête approprié.

Document est mon modèle d'entité pour représenter des documents. J'ai les fichiers eux-mêmes stockés sur le disque nommé d'après l'ID de l'enregistrement qui stocke ce document. Le nom de fichier et le type mime d'origine sont stockés dans l'objet Document.

@RequestMapping("/document/{docId}")
public void downloadFile(@PathVariable Integer docId, @RequestParam(value="inline", required=false) Boolean inline, HttpServletResponse resp) throws IOException {

    Document doc = Document.findDocument(docId);

    File outputFile = new File(Constants.UPLOAD_DIR + "/" + docId);

    resp.reset();
    if (inline == null) {
        resp.setHeader("Content-Disposition", "attachment; filename=\"" + doc.getFilename() + "\"");
    }
    resp.setContentType(doc.getContentType());
    resp.setContentLength((int)outputFile.length());

    BufferedInputStream in = new BufferedInputStream(new FileInputStream(outputFile));

    FileCopyUtils.copy(in, resp.getOutputStream());
    resp.flushBuffer();

}
0
Dan Ray