Как отобразить картинку в react приложении если картинка получается по запросу с заголовком аутентификации?

У меня есть код из react app:

import React from "react"
import axios from "axios";

class TrainerExercise extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            image: null
        }

        this.getImage()

        this.getImage = this.getImage.bind(this)
    }


    getImage() {
        const token = localStorage.getItem("jwt")
        if (token !== undefined && token !== null && token !== "undefined") {
            axios.get("http://localhost:8080/trainer/get_file", {
                headers: {
                    'Authorization': 'Bearer ' + token
                }})
                .then((res) => {
                    const blob = new Blob([res.data], {
                        type: "image/jpeg",
                      });

                    const url = Window.URL.createObjectURL(blob);
                    this.setState({image: url})
                })
                .catch((error) => {
                    console.error(error)
                })
        }
    }
    

    render() {
        if (this.props.exercise != null && this.state.image != null) {
            return (
                <div>
                    <p>{this.props.exercise.name}</p>
                    <p>{this.props.exercise.muscle}</p>
                    <p>{this.props.exercise.description}</p>
                    <img alt="Изображение упражнения" src={this.state.image}/>
                    <p>{this.props.exercise.video}</p>
                </div>
            )
        } else {
            return (
                <p>Выберите упражнение!</p>
            )
        }
    }
}

export default TrainerExercise

res я получаю такой:

config
: 
{transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …}
data
: 
"����\u0000\u0010JFIF\u0000\u0001\u0001\u0001\u000
headers
: 
AxiosHeaders {cache-control: 'no-cache, no-store, max-age=0, must-revalidate', content-length: '88719', content-type: 'image/jpeg', expires: '0', pragma: 'no-cache'}
request
: 
XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
status
: 
200
statusText
: 
""
[[Prototype]]
: 
Object

На сервере такая функция отправляет картинку:

@GetMapping("/get_file")
    public ResponseEntity<?> getFile() throws IOException {
        byte[] image = Files.readAllBytes(new File("D:\\Project\\fitness\\backend\\src\\main\\resources\\files\\testPhoto.jpeg").toPath());
        return ResponseEntity
                .status(HttpStatus.OK)
                .contentType(MediaType.valueOf("image/jpeg"))
                .body(image);
    }

Получить нормальный результат у меня не получается. Хотя когда отправляю файл просто по get-запросу без заголовков на аутентификацию и отключаю security, и просто вставляю такую url в src тега img, то все отображается.

Как я понимаю, мне надо сохранить файл и получить его url, который уже и вставлю в src тега img.


Ответы (1 шт):

Автор решения: Nikolay

Проблема была в том, что к headers надо добавить responseType: "arraybuffer", а я до этого его пытался добавить в headers, отсюда и были проблемы, по итогу метод getImage():

getImage() {
        const token = localStorage.getItem("jwt")
        if (token !== undefined && token !== null && token !== "undefined") {
            axios.get("http://localhost:8080/trainer/get_file", {
                headers: {
                    'Authorization': 'Bearer ' + token
                }, responseType: "arraybuffer"
            })
                .then((res) => {
                    const base64 = btoa(
                        new Uint8Array(res.data).reduce(
                          (data, byte) => data + String.fromCharCode(byte),
                          ''
                        )
                      )
                    this.setState({image: base64})
                })
                .catch((error) => {
                    console.error(error)
                })
        }
    }

А в render в тег img указал следующее:

<img alt="Изображение упражнения" src={`data:image/jpeg;charset=utf-8;base64,${this.state.image}`}/>

Теперь все ок!

→ Ссылка