Skip to content

Instantly share code, notes, and snippets.

@msandrini
Created November 30, 2018 08:37
Show Gist options
  • Save msandrini/7970c0ab448027aed539b085b5c9128b to your computer and use it in GitHub Desktop.
Save msandrini/7970c0ab448027aed539b085b5c9128b to your computer and use it in GitHub Desktop.
React component - Image tag with header auth
/* © Marcos Sandrini Lemos */
import { Component, Fragment, createElement } from 'react';
import PropTypes from 'prop-types';
import axios from 'axios';
const getMimeTypeFromExtension = (extension) => {
const allowedExtensions = ['jpeg', 'gif', 'png', 'webp'];
if (allowedExtensions.includes(extension)) return `image/${extension}`;
if (extension === 'jpg') return 'image/jpeg';
if (extension === 'svg') return 'image/svg+xml';
return 'image/*';
};
const transparentPixelImage = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';
export default class ImageWithAuth extends Component {
constructor() {
super();
this.state = {
dataUrl: transparentPixelImage
};
this.handleDataConverted = this.handleDataConverted.bind(this);
this.mimeType = null;
}
async componentDidMount() {
const { src } = this.props;
/* get image extension to be able to get the mime type */
const imageSrcChunks = src.split('.');
const extension = imageSrcChunks[imageSrcChunks.length - 1];
const headers = this.getHeaders(extension);
/* with headers set, prepare to make call */
const requestOptions = { headers, responseType: 'blob' };
this.setState({ isLoading: true });
/* make the call */
const { status, data: binaryData } = await axios.get(src, requestOptions);
/* if call returns OK, proceed into converting the image data */
if (status === 200) this.putBinaryDataIntoDataUrl(binaryData);
this.setState({ isLoading: false });
}
getHeaders(extension) {
const { authToken } = this.props;
this.mimeType = getMimeTypeFromExtension(extension);
return {
Authorization: authToken,
'Content-Type': mimeType
};
}
putBinaryDataIntoDataUrl(binary) {
/* convert image data from binary into dataURL using FileReader */
const reader = new FileReader();
const fileBlob = new Blob([binary], { type: this.mimeType });
/* when conversion is finished (load event), puts dataURL into the state */
reader.onload = this.handleDataConverted;
reader.readAsDataURL(fileBlob);
}
handleDataConverted(event) {
this.setState({ dataUrl: event.target.result });
}
render() {
const { altText, spinner } = this.props;
const { dataUrl, isLoading } = this.state;
return (
<Fragment>
{isLoading && spinner},
<img src={dataUrl} alt={altText} />
</Fragment>
);
}
}
ImageWithAuth.propTypes = {
src: PropTypes.string.isRequired,
altText: PropTypes.string,
spinner: PropTypes.node,
authToken: PropTypes.string
};
ImageWithAuth.defaultProps = {
altText: '',
spinner: null,
authToken: ''
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment