Search code examples
reactjsfirebasefirebase-realtime-databasenext.jsfirebase-storage

How can I check if the data_URL is returning an image of video ? - Firebase & Next.js/React


The image is uploaded to firebase and returned as a data_URL that looks like this:

https://firebasestorage.googleapis.com/v0/b/app_name/o/posts%2postId?alt=media&token=token

I am trying to check if the file type is a video or an image, then return a div depending on the "mediaType". Because firebase storage doesn't include the file extension in the url, it is difficult to determine the file type.

First attempt:

const [mediaType, setMediaType] = useState(null);
    
useEffect(() => {
    if (postImage) {
        const storageRef = firebase.storage().ref();
        storageRef.child(postImage).getDownloadURL().then(url => {
            fetch(url)
                .then(res => res.blob())
                .then(blob => {
                    let type = blob.type;
                    if (type.startsWith("image")) {
                        setMediaType("image");
                    } else if (type.startsWith("video")) {
                        setMediaType("video");
                    } else {
                        setMediaType("other");
                        console.log("Unknown file format: " + type);
                    }
                });
        });
    }
}, [postImage]);

Second attempt:

  const handleFile = async (e) => {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.onload = async (e) => {
        const dataURL = e.target.result;
        if (dataURL.startsWith('data:image/')) {
            setMediaType('image');
            setDataUrl(dataURL);
            console.log("Image: " + dataURL);
        } else if (dataURL.startsWith('data:video/')) {
            setMediaType('video');
            setDataUrl(dataURL);
            console.log("Video: " + dataURL);
        } else {
            let response = await fetch(dataURL);
            let type = response.headers.get("Content-Type");
            if (type.startsWith("image")) {
            setMediaType("image");
            setDataUrl(dataURL);
        } else if (type.startsWith("video")) {
            setMediaType("video");
            setDataUrl(dataURL);
        } else {
            setMediaType("other");
            console.log("Unknown file format: " + type);
        }
      }
    }
    reader.readAsDataURL(file);
 }

The div inside my return statement:

 <div className="w-full px-3">
   {mediaType === 'image' ? <img className="shadow-md w-full" src={postImage || 'default-image.jpg'} alt="" /> : null}
   {mediaType === 'video' ? <ReactPlayer layout="fill" url={postImage} config={{file:{attributes:{controlsList:'nodownload'}}}} controls onContextMenu={e => e.preventDefault()}/> : null}
   {mediaType === 'other' ? <p>File is not an image or video</p> : null}
 </div>

Solution

  • What I would do is add metadata while uploading the file to firebase. You can check the documentation to see how:

    //This is a metadata, you can customize these
    //as you can see the content type is set to be image/jpeg
    
    var newMetadata = {
      cacheControl: 'public,max-age=300',
      contentType: 'image/jpeg'
      .........
      .........
    };
    

    You will use this metadata while uploading the file using:

    storageRef.updateMetadata(newMetadata).......
    

    And when reading the file read out the metadata that you set to the file to for example detect its type:

    storageRef.getMetadata().then((metadata) => {
    //use this metadata to know the type here.......
    })
    

    Hope this gives you an idea of what to do.