Browse Source

feat: ImagePreview add onDownloadError API (#2093)

Co-authored-by: pointhalo <[email protected]>
YyumeiZhang 1 year ago
parent
commit
2303a57968

+ 1 - 0
content/show/image/index-en-US.md

@@ -503,6 +503,7 @@ import { Image, ImagePreview } from '@douyinfe/semi-ui';
 | onChange         | Event triggered by switching pictures                                                                                                                                    | (index: number) => void | - | |
 | onClose          | The callback function when the close button is clicked                                                                                                                   | () => void | - | |
 | onDownload       | Image download callback function                                                                                                                                         | (src: string, index: number) => void | - | |
+| onDownloadError     | Image download error callback                                                                                                                                | (src: string) => void | - | v2.54.0 |
 | onRotateLeft     | Callback for rotating the image                                                                                                                                          | (angle: number) => void | - | |
 | onNext           | Callback for switching pictures backwards                                                                                                                                | (index: number) => void | - | |
 | onPrev           | Callback for switching the picture forward                                                                                                                               | (index: number) => void | - | |

+ 1 - 0
content/show/image/index.md

@@ -505,6 +505,7 @@ import { Image, ImagePreview } from '@douyinfe/semi-ui';
 | onChange          | 切换图片触发的事件                                                                                                                                        | (index: number) => void | - | |
 | onClose           | 点击关闭按钮时的回调函数                                                                                                                                     | () => void | - | |
 | onDownload        | 图片下载回调函数                                                                                                                                         | (src: string, index: number) => void | - | |
+| onDownloadError     | 图片下载错误回调函数                                                                                                                                | (src: string) => void | - | v2.54.0 |
 | onRotateLeft      | 旋转图片的回调                                                                                                                                          | (angle: number) => void | - | |
 | onNext            | 向后切换图片的回调                                                                                                                                        | (index: number) => void | - | |
 | onPrev            | 向前切换图片的回调                                                                                                                                        | (index: number) => void | - | |

+ 2 - 1
packages/semi-foundation/image/previewInnerFoundation.ts

@@ -14,6 +14,7 @@ export interface PreviewInnerAdapter<P = Record<string, any>, S = Record<string,
     notifyRatioChange: (type: RatioType) => void;
     notifyRotateChange: (angle: number) => void;
     notifyDownload: (src: string, index: number) => void;
+    notifyDownloadError: (src: string) => void;
     registerKeyDownListener: () => void;
     unregisterKeyDownListener: () => void;
     disabledBodyScroll: () => void;
@@ -173,7 +174,7 @@ export default class PreviewInnerFoundation<P = Record<string, any>, S = Record<
         const setDownloadName = this._adapter.getSetDownloadFunc();
         const downloadSrc = imgSrc[currentIndex];
         const downloadName = setDownloadName ? setDownloadName(downloadSrc) : downloadSrc.slice(downloadSrc.lastIndexOf("/") + 1).split('?')[0];
-        downloadImage(downloadSrc, downloadName);
+        downloadImage(downloadSrc, downloadName, this._adapter.notifyDownloadError);
         this._adapter.notifyDownload(downloadSrc, currentIndex);
     }
 

+ 18 - 20
packages/semi-foundation/image/utils.ts

@@ -12,26 +12,24 @@ export const isTargetEmit = (event, targetClasses): boolean => {
     return isTarget;
 };
 
-export const downloadImage = (src: string, filename: string): void => {
-    const image = new Image();
-    image.src = src;
-    image.crossOrigin = "anonymous";
-    image.onload = (e): void => {
-        const eleLink = document.createElement("a");
-        eleLink.download = filename;
-        eleLink.style.display = "none";
-        eleLink.download = filename;
-        eleLink.href = src;
-        const canvas = document.createElement("canvas");
-        canvas.width = image.width;
-        canvas.height = image.height;
-        const context = canvas.getContext("2d");
-        context.drawImage(image, 0, 0, image.width, image.height);
-        eleLink.href = canvas.toDataURL("image/jpeg");
-        document.body.appendChild(eleLink);
-        eleLink.click();
-        document.body.removeChild(eleLink);
-    };
+export const downloadImage = async (src: string, filename: string, downloadErrorCb: (src: string) => void ) => {
+    try {
+        const response = await fetch(src);
+        if (response.ok) {
+            const blob = await response.blob();
+            const url = URL.createObjectURL(blob);
+            const link = document.createElement('a');
+            link.href = url;
+            link.download = filename;
+            link.click();
+            URL.revokeObjectURL(url);
+            link.remove();
+        } else {
+            downloadErrorCb(src);
+        }
+    } catch (error) {
+        downloadErrorCb(src);
+    }
 };
 
 export const crossMerge = (leftArr = [], rightArr = []) => {

+ 1 - 0
packages/semi-ui/image/interface.tsx

@@ -75,6 +75,7 @@ export interface PreviewProps extends BaseProps {
     onRatioChange?: (type: RatioType) => void;
     onRotateLeft?: (angle: number) => void;
     onDownload?: (src: string, index: number) => void;
+    onDownloadError?: (src: string) => void;
     setDownloadName?: (src: string) => string
 }
 

+ 4 - 0
packages/semi-ui/image/previewInner.tsx

@@ -139,6 +139,10 @@ export default class PreviewInner extends BaseComponent<PreviewInnerProps, Previ
                 const { onDownload } = this.props;
                 isFunction(onDownload) && onDownload(src, index);
             },
+            notifyDownloadError: (src: string) => {
+                const { onDownloadError } = this.props;
+                isFunction(onDownloadError) && onDownloadError(src);
+            },
             registerKeyDownListener: () => {
                 window && window.addEventListener("keydown", this.handleKeyDown);
             },