How does springboot actual combat code return pictures gracefully

Springboot actual combat code: [How to return pictures gracefully]

This article will summarize the common methods for returning pictures:

  1. Streaming return: mainly because the implementation is different, based on response and HttpConvertMessage
  2. base64 returns

Explanation

The picture can come from many places, it can be a local folder, it can also be a network stream, or a database binary, here for simplicity, local files are used.

@RestController
@RequestMapping("/")
public class ImgController {

    private String imgPath = "E:\\meme.png";

    private InputStream getImgInputStream() throws FileNotFoundException {
        return new FileInputStream(new File(imgPath));
    }

rely

The IOUtils used below should be familiar to everyone, from the classic common-io module

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

1. Return based on response

Very basic and simple way:

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. Return byte stream based on producers

2.1 Returning raw byte stream

Let's first see what happens if the byte stream directly returns the picture:

    /**
     * 试试直接返回字节流,不指定content-type
     */
    @GetMapping(value = "/img-byte")
    public byte[] getImageByte() throws IOException {
        final InputStream in = getImgInputStream();
        return IOUtils.toByteArray(in);
    }

The result is as follows: garbled, because the content-type is wrong
img-response garbled

2.2 Specify content-type to return byte stream

Use producers to specify types: here we specify 2 types and see what happens

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

The picture can be returned normally, but a closer look, the reason in the response header content-typeis image/jpeg
img jpeg
that when we request by default, springboot matches the first type of jpeg, although we are a png picture.

So how do we make it return content-type image/png?
By reading the source code comments, we know that we
produces
only need to pass the place we want when we request it Accept. The following is an example of postman:
image png

In fact, this method can also be used on the /img-byteinterface above , and it will not return garbled characters.
img-byte
At the same time, if we pass an unsupported type, we will get 406an error:
406

2.3 Download image files directly

If we want to directly pop up the download box, we can specify the content-type as: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);
    }

xiazai

    @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. base64 picture

import java.util.Base64;

    @GetMapping("/img-base64")
    public String getBase64Img() throws IOException {
        final byte[] bytes = IOUtils.toByteArray(getImgInputStream());
        return Base64.getEncoder().encodeToString(bytes);
    }

Front-end reception:

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();
Published 80 original articles · Like 319 · Visits 340,000+

Guess you like

Origin blog.csdn.net/jimo_lonely/article/details/105305522