Home > Software design >  Fetch image from C# Web API
Fetch image from C# Web API

Time:07-20

I am trying to download an image from a server (C# Web API). I send a FileStream as a response from the server and on the React client I read it as a blob. This works well with all file extensions except svg. I can't understand why.

Server action:

public async Task<ManagerResult> Get(Guid id)
{
    ManagerResult res = new ManagerResult();
    try
    {
         ImageModel image = await _mainContext.Images.FindAsync(id);
         string path = image.PhysicalPath;
         FileStream file = File.Open(path, FileMode.Open);
         res.Success = true;
         res.Data = file;
    }
    catch (Exception exc)
    {
         res.Success = false;
         res.Error = exc.Message;
    }
    return res;
}

I think that the whole idea of opening a stream and not closing it is bad, but I don't know how else to send a blob.

React side (fetch image):

const imagesGet = async (guid) => {
    const url = `${API_PREFIX}/images/get?id=${guid}`
    const response = await fetch(url, { method: 'GET', headers: authHeader() })
    //Error
    const error = responseError(response)
    if (error) {
        toast.error(error)
        return null
    }
    //Success
    const body = await response.blob()
    return body
}

React side (create object url):

useEffect(() => {
    api.images.get(guid).then((data) => {
        const url = URL.createObjectURL(data)
        setSRC(url)
    }).catch(console.log)
}, [guid, setSRC])

Result:

enter image description here

CodePudding user response:

I think, for a svg data, you need to specify blob type. Such crude is following.

const blob = new Blob([data], {
    type: 'image/svg xml; charset=utf8'
  });

As you know svg is determined by content-type field in a header. The following method helps to determine. If it is svg set type as I wrote, otherwise not, or just type: 'image' . If there is still an issue on type, you can make use of the answer.

async function urlIsSvg(url) {
  const r = await fetch(url, {method: 'HEAD'});
  return r.headers.get('content-type') === 'image/svg xml';
}

CodePudding user response:

To correctly send files, you need to use FileStreamResult (for Stream) or FileContentResolution (for byte[]). Just use the Controller.File(you_data, mime_type), it will choose the right Resilt on its own.

  • Related