In Angular, how do I load an image when I don't know the extension?

Viewed 1003

I have a login page that I want to be able to have custom branding on. When the customer is logged in, they will be able to upload either a .gif, .jpeg, or .png image which will then be used on the login page after they have logged out. The file will be stored with a generic filename in a predetermined location, so I will know all of that, I just won't know which file format was uploaded.

So basically, when a customer navigates to www.example.com/login/:id the application will load an image file from a publicly available mounted drive where the image is stored. The directory structure of the mounted drive where the image is stored will be something like /mnt/resource/client/:id/logo.*. The customer won't be authenticated yet, so I won't be able to access any database's.

My plan was to store the directory /mnt/resource/client in an environment variable, and when the login component loads up, I will append the id from the route params, and the filename, but at this point I won't know what the extension is.

Is there a way to be able to load an image in the html img tag with a location something like /mnt/resource/client/0001/logo.*? Also, logo.[png, jpg, gif] will be the only thing stored in this location.

EDIT: I attempted to use /mnt/resource/client/0001/logo.* as well as /mnt/resource/client/0001/logo but both give a 404. I figured it would, but thought I would try anyway.

Or, is there a better way to approach/solve this problem?

Also, I'm sorry if this is duplicate question, I attempted to search for related questions, but didn't find any, but also wasn't sure if I was correctly formulating my search query.

Also, let me know if there are any details I may have left out. Thanks in advance!

3 Answers

In order to load an image in html, you have to know the full path.

You've got a couple of options here:

  1. Store the full image name/extension in a db. Your application logic would then need to only allow access to parts of the db that are "public" from your login page. Your login page would request a standard image path, like example.com/resources/loginImage_clientID, and your server would do the db lookup based on that id, and return the correct image.
  2. Do server-side conversion of the login images so that you always use the same extension.

I'm also assuming you're not manually uploading these images for each client, so presumably you've already got the full image name and extension in a db somewhere so that you can verify which client is allowed to update which image.

I would suggest using race from RXjs:

const extensions = ['png', 'jpg'];

race(
   ...extensions.map(ext => this.http.get(`${file}.${ext}`).pipe(
     catchError(e => NEVER),
   )),
)

The race combinator will cancel other observables in the list thus cancelling the HTTP calls. catchError will turn an error into never completing observable, thus eliminating itself from the race.

But as stated by others, this will lead to poor performance, and you rather should learn server how to serve files without extension.

The file will be stored with a generic filename in a predetermined location, so I will know all of that, I just won't know which file format was uploaded.

It does not matter.

The server should store the image at a given URL without a file extension.

http://www.example.com/user/:id/logo

When the browser requests the resource the server includes the content type in the HTTP header response, and the browser will display the image automatically. It does not matter if it is PNG, JPEG or GIF.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types

If the server does not support content type detection, then it should send the image with a content-type: image/* type.

Most modern web servers allow you to configure what the content type is for a specific URL or range of URL, and most will auto detect the content type for static files.

Don't make meaningless 404 requests to your server.

Related