mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-11 10:12:00 +08:00
fix(downloads): Properly handle network errors, retries of downloads
This commit is contained in:
parent
1fc389c804
commit
3e8f7fbfd7
2 changed files with 23 additions and 34 deletions
|
@ -134,7 +134,6 @@ describe "FileDownloadStore", ->
|
|||
beforeEach ->
|
||||
spyOn(FileDownloadStore.Download.prototype, 'run').andCallFake -> Promise.resolve(@)
|
||||
spyOn(FileDownloadStore, '_prepareFolder').andCallFake -> Promise.resolve(true)
|
||||
spyOn(FileDownloadStore, '_cleanupDownload')
|
||||
|
||||
it "should make sure that the download file path exists", ->
|
||||
FileDownloadStore._runDownload(@testfile)
|
||||
|
|
|
@ -56,19 +56,6 @@ class Download
|
|||
|
||||
@promise = new Promise (resolve, reject) =>
|
||||
stream = fs.createWriteStream(@targetPath)
|
||||
|
||||
# We need to watch the request for `success` or `error`, but not fire
|
||||
# a callback until the stream has ended. This helper functions ensure
|
||||
# that resolve or reject is only fired once the stream has been closed.
|
||||
checkIfFinished = (action) =>
|
||||
# Wait for the stream to finish writing to disk and clear the request
|
||||
return if @request
|
||||
|
||||
if @state is State.Finished
|
||||
resolve(@) # Note: we must resolve with this
|
||||
else if @state is State.Failed
|
||||
reject(@)
|
||||
|
||||
@state = State.Downloading
|
||||
|
||||
NylasAPI.makeRequest
|
||||
|
@ -82,21 +69,24 @@ class Download
|
|||
.on "progress", (progress) =>
|
||||
@percent = progress.percent
|
||||
@progressCallback()
|
||||
.on "end", =>
|
||||
@request = null
|
||||
checkIfFinished()
|
||||
.pipe(stream)
|
||||
|
||||
success: =>
|
||||
# At this point, the file stream has not finished writing to disk.
|
||||
# Don't resolve yet, or the browser will load only part of the image.
|
||||
.on "error", (err) =>
|
||||
@request = null
|
||||
@state = State.Failed
|
||||
stream.end()
|
||||
if fs.existsSync(@targetPath)
|
||||
fs.unlinkSync(@targetPath)
|
||||
reject(@)
|
||||
|
||||
.on "end", =>
|
||||
return if @state is State.Failed
|
||||
@request = null
|
||||
@state = State.Finished
|
||||
@percent = 100
|
||||
checkIfFinished()
|
||||
stream.end()
|
||||
resolve(@) # Note: we must resolve with this
|
||||
|
||||
error: =>
|
||||
@state = State.Failed
|
||||
checkIfFinished()
|
||||
.pipe(stream)
|
||||
|
||||
ensureClosed: ->
|
||||
@request?.abort()
|
||||
|
@ -180,7 +170,10 @@ FileDownloadStore = Reflux.createStore
|
|||
@_downloads[file.id] = download
|
||||
@trigger()
|
||||
return download.run().finally =>
|
||||
@_cleanupDownload(download)
|
||||
download.ensureClosed()
|
||||
if download.state is State.Failed
|
||||
delete @_downloads[file.id]
|
||||
@trigger()
|
||||
|
||||
# Returns a promise that resolves with true or false. True if the file has
|
||||
# been downloaded, false if it should be downloaded.
|
||||
|
@ -213,7 +206,7 @@ FileDownloadStore = Reflux.createStore
|
|||
defaultPath = @_defaultSavePath(file)
|
||||
defaultExtension = path.extname(defaultPath)
|
||||
|
||||
NylasEnv.showSaveDialog {defaultPath: defaultPath}, (savePath) =>
|
||||
NylasEnv.showSaveDialog {defaultPath}, (savePath) =>
|
||||
return unless savePath
|
||||
NylasEnv.savedState.lastDownloadDirectory = path.dirname(savePath)
|
||||
|
||||
|
@ -234,16 +227,13 @@ FileDownloadStore = Reflux.createStore
|
|||
_abortFetchFile: (file) ->
|
||||
download = @_downloads[file.id]
|
||||
return unless download
|
||||
@_cleanupDownload(download)
|
||||
download.ensureClosed()
|
||||
@trigger()
|
||||
|
||||
downloadPath = @pathForFile(file)
|
||||
fs.exists downloadPath, (exists) ->
|
||||
fs.unlink(downloadPath) if exists
|
||||
|
||||
_cleanupDownload: (download) ->
|
||||
download.ensureClosed()
|
||||
@trigger()
|
||||
|
||||
_defaultSavePath: (file) ->
|
||||
if process.platform is 'win32'
|
||||
home = process.env.USERPROFILE
|
||||
|
|
Loading…
Reference in a new issue