Código de combate real de Springboot: [Cómo devolver imágenes con gracia]
Este artículo resumirá los métodos comunes para devolver imágenes:
- Retorno de transmisión: principalmente porque la implementación es diferente, en función de la respuesta y HttpConvertMessage
- devuelve base64
Explicación
La imagen puede provenir de muchos lugares, puede ser una carpeta local, también puede ser una secuencia de red o un binario de base de datos, aquí, por simplicidad, se utilizan archivos locales.
@RestController
@RequestMapping("/")
public class ImgController {
private String imgPath = "E:\\meme.png";
private InputStream getImgInputStream() throws FileNotFoundException {
return new FileInputStream(new File(imgPath));
}
Depende de
Los IOUtils que se usan a continuación deberían ser familiares para todos, desde el clásico módulo common-io
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
1. Retorno basado en la respuesta
De manera muy básica y simple:
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
/**
* 使用response输出图片流
*/
@GetMapping("/img-response")
public void getImage(HttpServletResponse resp) throws IOException {
final InputStream in = getImgInputStream();
resp.setContentType(MediaType.IMAGE_PNG_VALUE);
IOUtils.copy(in, resp.getOutputStream());
}
2. Devuelve el flujo de bytes basado en productores
2.1 Devolución de flujo de bytes sin formato
Primero veamos qué sucede si la secuencia de bytes devuelve directamente la imagen:
/**
* 试试直接返回字节流,不指定content-type
*/
@GetMapping(value = "/img-byte")
public byte[] getImageByte() throws IOException {
final InputStream in = getImgInputStream();
return IOUtils.toByteArray(in);
}
El resultado es el siguiente: ilegible, porque el tipo de contenido es incorrecto
2.2 Especifique el tipo de contenido para devolver la secuencia de bytes
Use productores para especificar tipos: aquí especificamos 2 tipos y vemos qué sucede
@GetMapping(value = "/img-media-type",
produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE})
public byte[] getImage() throws IOException {
final InputStream in = getImgInputStream();
return IOUtils.toByteArray(in);
}
La imagen se puede devolver normalmente, pero una mirada más cercana, la razón en el encabezado de respuesta content-type
es image/jpeg
que cuando solicitamos por defecto, springboot coincide con el primer tipo de jpeg, aunque somos una imagen png.
Entonces, ¿cómo hacemos que devuelva el tipo de contenido image/png
?
Al leer los comentarios del código fuente, sabemos que
solo necesitamos pasar el lugar que queremos cuando se lo solicite Accept
. El siguiente es un ejemplo de cartero:
De hecho, este método también se puede usar en la /img-byte
interfaz anterior y no devolverá caracteres ilegibles.
Al mismo tiempo, si pasamos un tipo no admitido, obtendremos 406
un error:
2.3 Descargar archivos de imagen directamente
Si queremos abrir directamente el cuadro de descarga, podemos especificar el tipo de contenido como:application/octet-stream
@GetMapping(value = "/img-file.png",
produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE})
public byte[] getImageFile() throws IOException {
final InputStream in = getImgInputStream();
return IOUtils.toByteArray(in);
}
@GetMapping(value = "/img/{iconId}", produces = {MediaType.IMAGE_PNG_VALUE, MediaType.IMAGE_JPEG_VALUE})
public byte[] getImage(@PathVariable String iconId) throws IOException {
final GisIcon icon = iconService.getById(iconId);
if (icon == null) {
throw new IllegalArgumentException("不存在此图片");
}
final FileInputStream fio = new FileInputStream(new File(iconService.getSavePath(icon.getUsername(),
icon.getName(), icon.getId())));
byte[] bytes = new byte[fio.available()];
log.info("读取文件结果:{}", fio.read(bytes, 0, fio.available()));
return bytes;
}
3. imagen base64
import java.util.Base64;
@GetMapping("/img-base64")
public String getBase64Img() throws IOException {
final byte[] bytes = IOUtils.toByteArray(getImgInputStream());
return Base64.getEncoder().encodeToString(bytes);
}
Recepción frontal:
function reqListener (base64) {
var body = document.getElementsByTagName("body");
var img = document.createElement("img");
img.src = "data:image/png;base64, "+base64;
body.appendChild(img);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://localhost:8013/img-base64");
oReq.send();