From e3fa393e1fd0045318b3b2b9385940c5abb6b65c Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 16 Jan 2022 20:10:30 +0100 Subject: [PATCH] fix: use direct link to gateway to download files License: MIT Signed-off-by: Henrique Dias --- src/bundles/files/actions.js | 3 +-- src/files/FilesPage.js | 16 +++++--------- src/files/download-file.js | 42 ------------------------------------ src/lib/files.js | 39 +++++++++++---------------------- 4 files changed, 19 insertions(+), 81 deletions(-) delete mode 100644 src/files/download-file.js diff --git a/src/bundles/files/actions.js b/src/bundles/files/actions.js index 650ee715d..bd1312860 100644 --- a/src/bundles/files/actions.js +++ b/src/bundles/files/actions.js @@ -418,9 +418,8 @@ const actions = () => ({ * @param {FileStat[]} files */ doFilesDownloadLink: (files) => perform(ACTIONS.DOWNLOAD_LINK, async (ipfs, { store }) => { - const apiUrl = store.selectApiUrl() const gatewayUrl = store.selectGatewayUrl() - return await getDownloadLink(files, gatewayUrl, apiUrl, ipfs) + return await getDownloadLink(files, gatewayUrl, ipfs) }), /** diff --git a/src/files/FilesPage.js b/src/files/FilesPage.js index a728fea53..34daa4b70 100644 --- a/src/files/FilesPage.js +++ b/src/files/FilesPage.js @@ -6,7 +6,6 @@ import { withTranslation, Trans } from 'react-i18next' import ReactJoyride from 'react-joyride' // Lib import { filesTour } from '../lib/tours' -import downloadFile from './download-file' // Components import ContextMenu from './context-menu/ContextMenu' import withTour from '../components/tour/withTour' @@ -27,8 +26,6 @@ const FilesPage = ({ files, filesPathInfo, pinningServices, toursEnabled, handleJoyrideCallback, isCliTutorModeEnabled, cliOptions, t }) => { const contextMenuRef = useRef() - const [downloadAbort, setDownloadAbort] = useState(null) - const [downloadProgress, setDownloadProgress] = useState(null) const [modals, setModals] = useState({ show: null, files: null }) const [contextMenu, setContextMenu] = useState({ isOpen: false, @@ -58,14 +55,12 @@ const FilesPage = ({ */ const onDownload = async (files) => { - if (downloadProgress !== null) { - return downloadAbort() - } + const { url, filename } = await doFilesDownloadLink(files) - const updater = (v) => setDownloadProgress(v) - const { url, filename, method } = await doFilesDownloadLink(files) - const { abort } = await downloadFile(url, filename, updater, method) - setDownloadAbort(() => abort) + const link = document.createElement('a') + link.download = filename // TODO: filename isn't working. Keep getting 'get.tar.gz' - is it being overwritten? + link.href = url + link.click() } const onAddFiles = (raw, root = '') => { if (root === '') root = files.path @@ -148,7 +143,6 @@ const FilesPage = ({ files={files.content} remotePins={remotePins} upperDir={files.upper} - downloadProgress={downloadProgress} onShare={(files) => showModal(SHARE, files)} onRename={(files) => showModal(RENAME, files)} onRemove={(files) => showModal(DELETE, files)} diff --git a/src/files/download-file.js b/src/files/download-file.js deleted file mode 100644 index 68f074c32..000000000 --- a/src/files/download-file.js +++ /dev/null @@ -1,42 +0,0 @@ -const downloadFile = (srcUrl, filename, progressCallback, method = 'GET') => { - const xhr = new window.XMLHttpRequest() - let total = 0 - - const abort = () => { - xhr.abort() - progressCallback(null) - } - - xhr.responseType = 'blob' - xhr.open(method, srcUrl, true) - - xhr.onload = (e) => { - progressCallback(100) - - const res = xhr.response - const blob = new window.Blob([res]) - const url = window.URL.createObjectURL(blob) - const a = document.createElement('a') - - document.body.appendChild(a) - a.style = 'display:none' - a.href = url - a.download = filename - a.click() - - window.URL.revokeObjectURL(url) - progressCallback(null) - } - - xhr.onprogress = (e) => { - total = e.lengthComputable ? e.total : (total || - xhr.getResponseHeader('X-Content-Length') || - xhr.getResponseHeader('Content-Length')) - - progressCallback((e.loaded / total) * 100) - } - - xhr.send() - return { abort } -} -export default downloadFile diff --git a/src/lib/files.js b/src/lib/files.js index 7f29878c0..3593a377b 100644 --- a/src/lib/files.js +++ b/src/lib/files.js @@ -38,28 +38,23 @@ export function normalizeFiles (files) { * @typedef {Object} FileDownload * @property {string} url * @property {string} filename - * @property {string} method * * @param {FileStat} file * @param {string} gatewayUrl - * @param {string} apiUrl * @returns {Promise} */ -async function downloadSingle (file, gatewayUrl, apiUrl) { - let url, filename, method +async function downloadSingle (file, gatewayUrl) { + let url, filename if (file.type === 'directory') { - const name = file.name || `download_${file.cid}` // Name is not always available. - url = `${apiUrl}/api/v0/get?arg=${file.cid}&archive=true&compress=true` - filename = `${name}.tar.gz` - method = 'POST' // API is POST-only + filename = `${file.name || `download_${file.cid}`}.tar.gz` + url = `${gatewayUrl}/api/v0/get?arg=${file.cid}&archive=true&compress=true` } else { - url = `${gatewayUrl}/ipfs/${file.cid}` filename = file.name - method = 'GET' + url = `${gatewayUrl}/ipfs/${file.cid}?download=true&filename=${file.name}` } - return { url, filename, method } + return { url, filename } } /** @@ -90,22 +85,15 @@ export async function makeCIDFromFiles (files, ipfs) { /** * * @param {FileStat[]} files - * @param {string} apiUrl + * @param {string} gatewayUrl * @param {IPFSService} ipfs * @returns {Promise} */ -async function downloadMultiple (files, apiUrl, ipfs) { - if (!apiUrl) { - const e = new Error('api url undefined') - return Promise.reject(e) - } - +async function downloadMultiple (files, gatewayUrl, ipfs) { const cid = await makeCIDFromFiles(files, ipfs) - return { - url: `${apiUrl}/api/v0/get?arg=${cid}&archive=true&compress=true`, - filename: `download_${cid}.tar.gz`, - method: 'POST' // API is POST-only + url: `${gatewayUrl}/api/v0/get?arg=${cid}&archive=true&compress=true`, + filename: `download_${cid}.tar.gz` } } @@ -113,16 +101,15 @@ async function downloadMultiple (files, apiUrl, ipfs) { * * @param {FileStat[]} files * @param {string} gatewayUrl - * @param {string} apiUrl * @param {IPFSService} ipfs * @returns {Promise} */ -export async function getDownloadLink (files, gatewayUrl, apiUrl, ipfs) { +export async function getDownloadLink (files, gatewayUrl, ipfs) { if (files.length === 1) { - return downloadSingle(files[0], gatewayUrl, apiUrl) + return downloadSingle(files[0], gatewayUrl) } - return downloadMultiple(files, apiUrl, ipfs) + return downloadMultiple(files, gatewayUrl, ipfs) } /**