-
-
Save bluesealjs/00b886d8e5c42c5173d649d66189455f to your computer and use it in GitHub Desktop.
create download link for protected resources using blob
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { observable } from 'mobx'; | |
import { observer } from 'mobx-react'; | |
import { DocumentModel } from '../models'; | |
import { Icon, Tooltip } from '../controls'; | |
@observer | |
export class Component extends React.Component<{ | |
record: DocumentModel, | |
privateKey: string, | |
getLabel: (privateKey: string, url: string) => Promise<string>, | |
}, {}> { | |
@observable isLoading = false; | |
@observable isError = false; | |
@observable result: string | undefined; | |
url: string = ''; | |
componentWillUnmount() { | |
URL.revokeObjectURL(this.url); | |
} | |
loadFile = () => { | |
const { record, privateKey } = this.props; | |
this.isLoading = true; | |
this.props.getLabel(privateKey, record.url) | |
.then(res => { this.isLoading = false; this.result = res; }) | |
.catch(err => { this.isLoading = false; this.isError = true; }); | |
} | |
render() { | |
if (this.isLoading) { | |
return (<Icon type={'loading'} />); | |
} | |
if (this.isError) { | |
return ( | |
<Tooltip title={'Label not available'}> | |
<Icon type="exclamation-circle-o" /> | |
</Tooltip> | |
); | |
} | |
if (this.result) { | |
const name = `${this.props.record.id}.${this.props.record.fileType}`; | |
this.url = URL.createObjectURL(new Blob([this.result])); | |
return ( | |
<Tooltip title={'Download is ready'}> | |
<a href={this.url} download={name}> | |
<Icon type={'download'} /> | |
</a> | |
</Tooltip> | |
); | |
} | |
return ( | |
<a onClick={() => { this.loadFile(); }}>{'Check'}</a> | |
); | |
} | |
} | |
import { connect } from 'react-redux'; | |
import { RootState } from '@src/modules'; | |
import { SitesSelectors } from '@src/modules/sites'; | |
import { getLabel } from '@src/services'; | |
const mapStateToProps = (state: RootState) => ({ | |
privateKey: SitesSelectors.getSelectedSitePrivateKey(state), | |
getLabel: getLabel, | |
}); | |
const Connected = connect(mapStateToProps, { | |
})(Component); | |
export default Connected; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import { observable } from 'mobx'; | |
import { observer } from 'mobx-react'; | |
import { DocumentModel } from '../models'; | |
import { Icon, Tooltip } from '../controls'; | |
@observer | |
export class Component extends React.Component<{ | |
record: DocumentModel, | |
privateKey: string, | |
getLabel: (privateKey: string, url: string) => Promise<string>, | |
}, {}> { | |
@observable isLoading = false; | |
@observable isError = false; | |
@observable result: string | undefined; | |
url: string = ''; | |
componentWillUnmount() { | |
URL.revokeObjectURL(this.url); | |
} | |
loadFile = () => { | |
const { record, privateKey } = this.props; | |
this.isLoading = true; | |
this.props.getLabel(privateKey, record.url) | |
.then(res => { this.isLoading = false; this.result = res; }) | |
.catch(err => { this.isLoading = false; this.isError = true; }); | |
} | |
render() { | |
if (this.isLoading) { | |
return (<Icon type={'loading'} />); | |
} | |
if (this.isError) { | |
return ( | |
<Tooltip title={'Label not available'}> | |
<Icon type="exclamation-circle-o" /> | |
</Tooltip> | |
); | |
} | |
if (this.result) { | |
const name = `${this.props.record.id}.${this.props.record.fileType}`; | |
this.url = URL.createObjectURL(new File([this.result], 'label.txt')); | |
return ( | |
<Tooltip title={'Download is ready'}> | |
<a href={this.url} download={name}> | |
<Icon type={'download'} /> | |
</a> | |
</Tooltip> | |
); | |
} | |
return ( | |
<a onClick={() => { this.loadFile(); }}>{'Check'}</a> | |
); | |
} | |
} | |
import { connect } from 'react-redux'; | |
import { RootState } from '@src/modules'; | |
import { SitesSelectors } from '@src/modules/sites'; | |
import { getLabel } from '@src/services'; | |
const mapStateToProps = (state: RootState) => ({ | |
privateKey: SitesSelectors.getSelectedSitePrivateKey(state), | |
getLabel: getLabel, | |
}); | |
const Connected = connect(mapStateToProps, { | |
})(Component); | |
export default Connected; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
You can allocate an arbitrary object in the browser memory (RAM) as a Blob or File Objects, | |
then you can access it later via an URL string created using URL.createObjectURL. | |
This URL will serve the stored object as long as there is some reference to it, and then will be grabage collected automatically. | |
I think it is a good practice to free it explicitly with URL.revokeObjectURL, otherwise it will be allocated for a long time (about a day?). | |
TIP: Note a difference between Blob and File Objects. Blob is stored in the memory, File on the file system. | |
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management | |
chrome://blob-internals/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment