All files / src/components/fileOperator FileOperatorUtils.ts

59.57% Statements 56/94
70.58% Branches 24/34
40.9% Functions 9/22
62.22% Lines 56/90

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152            66x 5x 3x   2x     66x 6x 3x   3x     66x 7x 3x   4x     66x 6x     66x 6x     66x 1x 1x 1x 1x 1x 1x 1x 1x     66x 66x 66x 66x 66x 66x 66x 66x 66x 66x 66x 66x 66x 66x   66x 14x 6x 6x   8x       66x 9x 3x   6x     66x                             66x                                               66x                           66x                       66x 3x         3x 3x    
import { AttachmentOperation, ExtendUploadFile, HttpErrorProps } from "@props/RecordProps";
import { RcFile } from "antd/es/upload";
import { downloadAttachment } from "@utils/FetchUtils";
import { openErrorNotification, openInfoNotification } from "@utils/NotificationUtils";
import i18n from "i18next";
 
export const isSuccess = (file: ExtendUploadFile): boolean => {
  if (file == null || !("status" in file)) {
    return false;
  }
  return (file.status === 'done');
};
 
export const isFail = (file: ExtendUploadFile): boolean => {
  if (file == null || !("status" in file)) {
    return false;
  }
  return file.status === 'error';
};
 
export const isRemoved = (file: ExtendUploadFile): boolean => {
  if (file == null || !("status" in file)) {
    return false;
  }
  return file.status === 'removed';
};
 
export const isUploadOperation = (operation: AttachmentOperation | undefined): boolean => {
  return operation === "upload";
};
 
export const isDeleteOperation = (operation: AttachmentOperation | undefined): boolean => {
  return operation === "delete";
};
 
export const downloadFile = (blob: Blob, file: ExtendUploadFile): void => {
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = file.name;
  a.target = '_blank';
  a.click();
  window.URL.revokeObjectURL(url);
  a.remove();
};
 
export const ImageFileExtensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg'];
export const CsvFileExtensions = ['csv'];
export const PdfFileExtensions = ['pdf'];
export const ExcelFileExtensions = ['xls', 'xlsx'];
export const WordFileExtensions = ['doc', 'docx'];
export const PowerpointFileExtensions = ['ppt', 'pptx'];
export const TextFileExtensions = ['txt'];
export const JsonFileExtensions = ['json'];
export const MarkdownFileExtensions = ['md'];
export const CodeFileExtensions = ['groovy', 'css', 'js'];
export const HtmlFileExtensions = ['html', 'htm'];
export const XmlFileExtensions = ['jrxml', 'xml'];
export const VideoFileExtensions = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv', 'mpg', 'mpeg', '3gp', 'm4v'];
export const AudioFileExtensions = ['mp3', 'wav', 'wma', 'flac', 'aac', 'ogg', 'm4a', 'aiff', 'ape', 'alac'];
 
export const getFileType = (file: ExtendUploadFile): string => {
  if (file == null || !('name' in file)) {
    console.warn(`Unable to get file type of [${JSON.stringify(file)}], returning ("")`);
    return "";
  }
  return (file.name.lastIndexOf(".") === -1) ?
    "" : file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase();
};
 
export const isFileOfType = (file: ExtendUploadFile, extensions: string[]): boolean => {
  if (extensions == null || extensions.length === 0) {
    return false;
  }
  return extensions.includes(getFileType(file)?.toLowerCase() ?? "");
};
 
export const getBlob = async (file: RcFile, preview?: boolean): Promise<Blob | void> => {
  const { id } = (file as ExtendUploadFile);
  if (id != null) {
    try {
      return downloadAttachment(id, preview);
    } catch (e) {
      console.error(`Failed to download file ${file.name}: ${e}`);
    }
  }
  return new Promise(() => {
    return file;
  });
};
 
//ATTENTION 如果 Word, Powerpoint 文件没有上传, 则无法预览
export const getBase64 = async (file: ExtendUploadFile): Promise<unknown> => {
  const { id } = (file as ExtendUploadFile);
  if (id != null) {
    try {
      const blob = await downloadAttachment(id, true);
      return await new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(blob);
        reader.onload = () => resolve(reader.result);
        reader.onerror = error => reject(error);
      });
    } catch (e: unknown) {
      console.error(`Failed to get file ${file.name} content: ${e}`);
      throw e;
    }
  }
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file as RcFile);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
};
 
export const onDownload = (file: ExtendUploadFile): void => {
  if (file.id == null) {
    return;
  }
  downloadAttachment(file.id).then(blob => {
    downloadFile(blob, file);
    openInfoNotification(i18n.t('File downloaded', { fileName: file.name }));
  }).catch(e => {
    const errorMsgKey: string = getErrorMsgKey(e);
    openErrorNotification(i18n.t(errorMsgKey, { fileName: file.name, error: e }));
    console.error(`Failed to download file ${file.name}: ${e}`);
  });
};
 
export const isPreviewable = (file: ExtendUploadFile): boolean => {
  if (file == null) {
    return false;
  }
  return isFileOfType(file, [
    ...CsvFileExtensions, ...PdfFileExtensions, ...WordFileExtensions, ...ExcelFileExtensions,
    ...PowerpointFileExtensions, ...HtmlFileExtensions, ...ImageFileExtensions,
    ...VideoFileExtensions, ...AudioFileExtensions, ...CodeFileExtensions, ...JsonFileExtensions,
    ...MarkdownFileExtensions, ...XmlFileExtensions
  ]);
};
 
export const getErrorMsgKey = (e: HttpErrorProps): string => {
  const errorKeyMap: { [propName: number]: string; } = {
    406: "No permission to download or preview the attachment",
    403: "No permission to download or preview the attachment",
    500: "Backend error when download or preview the attachment",
  };
  const errorMsgKey: string = (errorKeyMap[e.status] as string) ?? "Failed to download or preview this file";
  return errorMsgKey;
};