FileDecrypter: use an actual link to save the file

triggering click on a hidden element will not always work. Plus that
it's good to have user consent
This commit is contained in:
Peter Cai 2020-02-19 16:08:15 +08:00
parent 171bba517d
commit 1140040bcc
No known key found for this signature in database
GPG Key ID: 71F5FB4E4F3FD54F
2 changed files with 28 additions and 27 deletions

View File

@ -59,20 +59,6 @@ progressText = (progress) ->
else
txt
# Browser: save a file from ArrayBuffer
browserSaveFile = (mime, name, file) ->
link = document.createElement 'a'
link.style.display = 'none';
document.body.appendChild link
blob = new Blob [file],
type: mime
objUrl = URL.createObjectURL blob
link.href = objUrl
link.download = name
link.click()
# Convert a file size to human-readable form
# <https://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable-string>
humanFileSize = (bytes, si) ->
@ -102,6 +88,5 @@ export {
isBrowser,
isText,
progressText,
browserSaveFile,
humanFileSize
}

View File

@ -19,6 +19,7 @@ class FileDecrypter extends React.Component
progress: 0
key: key
iv: iv
downloaded: null
componentDidMount: ->
# Fetch metadata to show to user
@ -60,9 +61,11 @@ class FileDecrypter extends React.Component
@setState
decrypting: true
decrypted = await crypto.decryptFile @state.key, @state.iv, file
util.browserSaveFile @state.mime, @state.name, decrypted
blob = new Blob [decrypted],
type: @state.mime
@setState
decrypting: false
downloaded: blob
render: ->
<div className="content-pastebin">{
@ -73,18 +76,31 @@ class FileDecrypter extends React.Component
<p>{@state.name}</p>
<p>{@state.mime}</p>
<p>{util.humanFileSize @state.length}</p>
<button
className="button-blue"
disabled={@state.downloading}
onClick={@downloadFile}
>{
if not @state.downloading
"Download"
else if @state.decrypting
"Decrypting"
{
if not @state.downloaded
<button
className="button-blue"
disabled={@state.downloading}
onClick={@downloadFile}
>{
if not @state.downloading
"Download"
else if @state.decrypting
"Decrypting"
else
util.progressText @state.progress
}</button>
else
util.progressText @state.progress
}</button>
# Use an actual link here instead of triggering click
# on a hidden link, because on some browsers it doesn't work
<a
className="button-blue"
href={URL.createObjectURL @state.downloaded}
download={@state.name}
>
Save File
</a>
}
</div>
}</div>