diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 84dbc9f47..711ccfd08 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -45,6 +45,7 @@ "eslint-plugin-vue": "^7.9.0", "eventsource-polyfill": "^0.9.6", "file-loader": "^3.0.1", + "file-saver": "^2.0.5", "hls.js": "^0.14.17", "karma": "^6.3.2", "karma-chrome-launcher": "^3.1.0", @@ -6268,6 +6269,11 @@ "node": ">= 4" } }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -20363,6 +20369,11 @@ } } }, + "file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index e86abaf90..b0c68b6d3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -55,6 +55,7 @@ "eslint-plugin-vue": "^7.9.0", "eventsource-polyfill": "^0.9.6", "file-loader": "^3.0.1", + "file-saver": "^2.0.5", "hls.js": "^0.14.17", "karma": "^6.3.2", "karma-chrome-launcher": "^3.1.0", diff --git a/frontend/src/common/download.js b/frontend/src/common/download.js index 201652540..2a0f0ac89 100644 --- a/frontend/src/common/download.js +++ b/frontend/src/common/download.js @@ -28,6 +28,12 @@ https://docs.photoprism.org/developer-guide/ */ +import saveAs from "file-saver"; + +// Detect Safari browser. +const isSafari = + navigator.appVersion.indexOf("Safari/") !== -1 && navigator.appVersion.indexOf("Chrome") === -1; + // Downloads a file from the server. export default function download(url, name) { // Abort if download url is empty. @@ -36,6 +42,23 @@ export default function download(url, name) { return; } + if (isSafari) { + const xhr = new XMLHttpRequest(); + xhr.open("GET", url); + xhr.responseType = "blob"; + + xhr.onload = function () { + saveAs(xhr.response, name); + }; + + xhr.onerror = function () { + console.error("download failed", url); + }; + + xhr.send(); + return; + } + // Create download link. const link = document.createElement("a");