This is very easy to do 80% of the way, and difficult to do with the remaining 20%. The last mile of file validation is extremely fickle because it requires an understanding of what the uploading library is doing under the hood. You can minimize your risk by carefully choosing files to accept, understanding how they're parsed by your libraries and correctly disallowing everything else.
Practically speaking, you should at a minimum:
1. Whitelist acceptable file types,
2. Perform server-side, not client-side validation,
3. Validate the file types not only by extension, but by contents,
4. Disallow filenames from being set by user input, and ideally hash them before presenting them back,
5. Store the files on a separate host/CDN,
6. Only allow the uploader to retrieve files uploaded by the user, and not from local or remote resources. If you must allow local directories, maintain strict permissions, and do not allow loopback resources.
That's a great start. To go further, you should investigate which library to use carefully and consider how legitimate files you are choosing to whitelist can still be dangerous. For example, you can trigger an XSS with a valid SVG. You can attack system memory with fraudulent JPG sizes. You can trigger server-side request forgery by uploading 127.0.0.1, etc.
Obviously, a trickier problem when those images are encrypted.
WhatsApp is end to end encrypted, so how is server side validation possible?
In this specific scenario, the files should be validated before a user is presented with them and after they are received and decrypted. The client-side validation is only so that the attacker cannot bypass it and leave the server vulnerable; you can instead offload this to the other party, which in this case is client 2 in a client <-> client communication rather than client <-> server communication.
The point is that it happens somewhere out of an attacker's control in a trusted environment. Obviously, the same limitation applies to server-side validation, which is that the file must be validated without triggering a latent exploit within it. That's why it's also important to understand the parsing libraries.