From ea6576d2b6b25baf5c5f98293fa9e5e7115ed8c7 Mon Sep 17 00:00:00 2001 From: Andy Bao Date: Sun, 25 Apr 2021 07:08:49 -0400 Subject: [PATCH] CloudStorage (FTP): Do not buffer entire download in memory (#7597) --- frontend/apps/cloudstorage/ftp.lua | 20 +++++++++----------- frontend/apps/cloudstorage/ftpapi.lua | 13 +++++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/frontend/apps/cloudstorage/ftp.lua b/frontend/apps/cloudstorage/ftp.lua index 61a1286b8..e1d34d5ad 100644 --- a/frontend/apps/cloudstorage/ftp.lua +++ b/frontend/apps/cloudstorage/ftp.lua @@ -22,18 +22,16 @@ end function Ftp:downloadFile(item, address, user, pass, path, close) local url = FtpApi:generateUrl(address, util.urlEncode(user), util.urlEncode(pass)) .. item.url logger.dbg("downloadFile url", url) - local response = FtpApi:ftpGet(url, "retr") + path = util.fixUtf8(path, "_") + local file, err = io.open(path, "w") + if not file then + UIManager:show(InfoMessage:new{ + text = T(_("Could not save file to %1:\n%2"), BD.filepath(path), err), + }) + return + end + local response = FtpApi:ftpGet(url, "retr", ltn12.sink.file(file)) if response ~= nil then - path = util.fixUtf8(path, "_") - local file, err = io.open(path, "w") - if not file then - UIManager:show(InfoMessage:new{ - text = T(_("Could not save file to %1:\n%2"), BD.filepath(path), err), - }) - return - end - file:write(response) - file:close() local __, filename = util.splitFilePathName(path) if G_reader_settings:isTrue("show_unsupported") and not DocumentRegistry:hasProvider(filename) then UIManager:show(InfoMessage:new{ diff --git a/frontend/apps/cloudstorage/ftpapi.lua b/frontend/apps/cloudstorage/ftpapi.lua index 31379afbd..c85b94ed5 100644 --- a/frontend/apps/cloudstorage/ftpapi.lua +++ b/frontend/apps/cloudstorage/ftpapi.lua @@ -20,16 +20,15 @@ function FtpApi:generateUrl(address, user, pass) return generated_url end -function FtpApi:ftpGet(u, command) - local t = {} +function FtpApi:ftpGet(u, command, sink) local p = url.parse(u) p.user = util.urlDecode(p.user) p.password = util.urlDecode(p.password) p.command = command - p.sink = ltn12.sink.table(t) + p.sink = sink p.type = "i" -- binary local r, e = ftp.get(p) - return r and table.concat(t), e + return r, e end function FtpApi:listFolder(address_path, folder_path) @@ -38,12 +37,14 @@ function FtpApi:listFolder(address_path, folder_path) local type local extension local file_name - local ls_ftp = self:ftpGet(address_path, "nlst") + local tbl = {} + local sink = ltn12.sink.table(tbl) + local ls_ftp = self:ftpGet(address_path, "nlst", sink) if ls_ftp == nil then return false end if folder_path == "/" then folder_path = "" end - for item in (ls_ftp..'\n'):gmatch'(.-)\r?\n' do + for item in (table.concat(tbl)..'\n'):gmatch'(.-)\r?\n' do if item ~= '' then file_name = item:match("([^/]+)$") extension = item:match("^.+(%..+)$")