Carregar imagem blob dentro do src da img

Tenho um banco de dados que armazena o nome de uma imagem, por exemplo:imagem.jpeg.
Em seguida, tenho uma função na minha api que requisita essa imagem, usando fetch:

getMedia: async (filename) => {
    let blob = await (await fetch(URL+mediaPath+filename, {mode: 'no-cors'})).blob();
    return blob;
  }

O blob retornado é um objeto, que eu transformo em url usando URL.createObjectURL(blob). Então, no final o resultado é a url: blob:http://localhost:3000/a24caa0f-26b3-4e27-bfad-b1867718a068.
Eu pego essa url e coloco no src de uma img.

O problema é que a imagem não aparece e não tem erros no console. Eu estou usando react-router-dom, pensei que as rotas que configurei estariam influenciando nisso, mas não sei o que fazer!

const [avatar, setAvatar] = useState(null);

getMedia: async (filename) => {
    const blob = await ....

    const reader = new FileReader();
    reader.onloadend = () => {
      setAvatar(reader.result);
    };
    reader.onerror = () => console.log('There was an error');
    reader.readAsDataURL(blob);
}

<img src={avatar} alt="Alguma coisa"/>

Fiz isso e o reader.result está retornando só "data:"
Também notei q o blob retornado pela requisição está especificando size: 0 e type: '', mas se eu olhar na aba network do devtools a imagem foi encontrada e o status é 200…

tenta fazer isso, o código fica mais limpo e mais entendivel

const response = await fetch(URL+mediaPath+filename, {
   mode: 'no-cors'
});

const blob = response.blob();

Mesma coisa…
Eu dei uma lida: parece que, quando se usa mode: 'no-cors' no fetch(), a resposta sempre vem com type: 'opaque', e se a resposta vem com esse type automaticamente o blob terá size: 0, type: '', e isso o torna inútil pra métodos como URL.createObjectURL() e, provavelmente, o reader.readAsDataURL deve se encaixar nisso.

Talvez funcionaria se eu não usasse o mode: 'no-cors', mas se eu não usa-lo eu recebo esse erro do CORS:
Access to fetch at 'http://localhost:8000/api/media/images/6226303b041ec.jpeg' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
O jeito seria fazer uma página php retornar a imagem (nem sei se é possível), já que nessa página daria pra configurar a header ‘Access-Control-Allow-Origin’

Detalhe que o server onde estou servindo as imagens é diferente do front end do react

cara, pq vc não usa uma lib mais atual tipo o axios?

e outra, o servidor é seu?

Só não uso porque o fetch sempre deu conta das minhas necessidades, mas será q é bom usar aqui?

E o servidor é meu sim, mas durante o desenvolvimento do aplicativo aqui, eu rodo a api em um server php e o react no server do npm. A ideia é que eu possa deixar tudo junto quando eu buildar o front end

eu prefiro


pq nao libera o cors pelo php? não dá? (nao manjo de php)

O que eu faço é colocar isso no topo de todo arquivo php:

header('Access-Control-Allow-Origin: http://localhost:3000');

Isso arruma aquele erro do CORS. Mas obviamente não dá pra fazer isso numa imagem, e pelo meu conhecimento não tem outra maneira de fazer isso

o que vem no retorno da sua api?


isso?

blob:http://localhost:3000/a24caa0f-26b3-4e27-bfad-b1867718a068.


Dá uma olhada nesse topico aqui sobre CORS no php:

Da API eu recebo:

Blob: {
  size: 0,
  type: ''
}

A url é criada quando eu coloco esse Blob no método URL.createObjectURL(), por algum motivo, mas não é uma url válida justamente pela composição do objeto.

Eu consegui “resolver”, mas a imagem só vai aparecer quando o aplicativo for ‘buildado’ e colocado no mesmo server da api. Pro app que estou fazendo não faz a menor diferença, então tá tudo certo. Esse erro do cors vai ter que ficar no ar pelo jeito

baixa essa extensao:

se der certo o cors, ve os headers que ele manda, e coloca junto no react

Atualizando…

Na própria docs do php tem esse exemplo usando fpassthru:
https://www.php.net/manual/pt_BR/function.fpassthru.php#example-2099

<?php

// abre o arquivo em modo binário
$name = './img/ok.png';
$fp = fopen($name, 'rb');

// envia os headers
header("Content-Type: image/png");
header("Content-Length: ".filesize($name));

// manda a imagem e pára o script
fpassthru($fp);
exit;

Deve-se garantir que não haverão espaços antes ou depois da tag do php <?php ?>
Também dá pra omitir o fechamento da tag, assim garantindo que não vai ter espaço depois dela.

Usei esse exemplo e adicionei as headers para o cors: Access-Control-Allow-Origin e Access-Control-Allow-Headers.