Gist file storage
by Bret Lowrey
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="download"></div>
<div class="component" id="fileInput"></div>
CSS
.pull-right {
float: right !important;
}
label {
font-size: 12px;
}
.header {
font-weight: bold;
}
html {
height: 80%;
}
.outputUrl {
width: 80%;
text-overflow: ellipsis;
text-align: center;
}
.content {
height: 100%;
margin: 5px;
}
.component {
height: 100%;
width: 95%;
display: inline-block;
}
body {
height: 100%;
margin: 40px auto;
max-width: 752px;
background: #eee;
line-height: 1.6;
font-size: 18px;
font-family: arial, sans-serif;
color: #444;
padding: 0 10px
}
label {
max-width: 80%;
font-size: 1.25rem;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
display: inline-block;
overflow: hidden;
padding: 0.625rem 1.25rem;
}
form label {
color: #009999;
}
form label figure {
width: 100px;
height: 100px;
border-radius: 50%;
background-color: #009999;
display: block;
padding: 20px;
margin: 0 auto 10px;
}
form label svg {
width: 100%;
height: 100%;
fill: #f1e5e6;
}
.inputfile {
width: 0.1px;
height: 0.1px;
opacity: 0;
position: absolute;
z-index: -1;
}
.uploadContent {
text-align: center;
width: 100%;
}
.downloadContent {
color: #009999;
}
.outputUrl {
padding: 5px;
border: transparent;
border-radius: 8px;
text-decoration: none;
color: #666;
font-size: 14px;
line-height: 120%;
}
.outputUrl:hover {
background-color: #ffffff;
}
Babel + JSX
class GistDownload extends React.Component {
constructor() {
super();
this.state = {
caption: 'Downloading...'
};
this.downloadGist(new URLSearchParams(window.location.search).get('url'));
}
componentDidMount() {
}
dataUrlToBlob(dataUrl) {
var arr = dataUrl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
}
downloadGist(url) {
const saveAs = (function() {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return (data, fileName) => {
const blob = new Blob([data], {
type: "octet/stream"
});
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
const downloading = setInterval(() => {
let numDots = this.state.caption.split('.').length - 1;
numDots = numDots < 3 ? numDots + 1 : 0;
this.setState({
caption: 'Downloading' + '.'.repeat(numDots)
});
}, 500);
const filename = decodeURIComponent(url.split('/').pop());
fetch(url)
.then(response => {
clearInterval(downloading);
this.setState({
caption: '👍'
});
return response.text();
})
.then(blob => saveAs(this.dataUrlToBlob(blob), filename));
}
handleChange(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
this.uploadGist(file, reader.result);
}
}
render() {
return (
<div className="downloadContent">
{this.state.caption}
</div>
);
}
}
class FileInput extends React.Component {
constructor() {
super();
...