All files / src/upload uploadFile.ts

0% Statements 0/30
0% Branches 0/20
0% Functions 0/9
0% Lines 0/30

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                                                                                                                                                                                                                                   
export interface ProgressInfo {
  /**
   * 文件总大小
   */
  total: number;
 
  /**
   * 已上传部分大小
   */
  loaded: number;
 
  /**
   * 百分比
   */
  percent: number;
}
 
export interface UploadEventContext {
  /**
   * 进度事件
   */
  event: ProgressEvent;
 
  /**
   * XHR 对象
   */
  xhr: XMLHttpRequest;
 
  /**
   * 当前文件
   */
  file: File;
}
 
export interface UploadOption {
  action: string;
  file: File;
  filename: string;
  data?: object;
  headers?: object;
  withCredentials?: boolean;
  onProgress?: (progress: ProgressInfo, context: UploadEventContext) => void;
  onSuccess?: (result: object | string, context: UploadEventContext) => void;
  onError?: (error: Error, context: UploadEventContext) => void;
}
 
export function upload({
  action,
  file,
  filename,
  data = {},
  headers = {},
  withCredentials = false,
  onProgress = () => null,
  onSuccess = () => null,
  onError = () => null,
}: UploadOption) {
  const formData = new FormData();
 
  const xhr = new XMLHttpRequest();
 
  xhr.onload = event => {
    if (!(xhr.status >= 200 && xhr.status < 300)) {
      const error = new Error(`${xhr.status} ${xhr.statusText}`);
      onError(error, { event, xhr, file });
      return;
    }
 
    const text = xhr.responseText || xhr.response;
    try {
      const data = JSON.parse(text);
      onSuccess(data, { event, xhr, file });
    } catch (err) {
      onSuccess(text, { event, xhr, file });
    }
  };
 
  xhr.onerror = event =>
    onError(new Error("Http Request Error"), { event, xhr, file });
 
  if (onProgress && xhr.upload) {
    xhr.upload.onprogress = event => {
      if (event.lengthComputable && event.total) {
        onProgress(
          {
            total: event.total,
            loaded: event.loaded,
            percent: (event.loaded / event.total) * 100,
          },
          { event, xhr, file }
        );
      }
    };
  }
 
  Object.keys(data).forEach(key => {
    formData.append(key, data[key]);
  });
 
  formData.append(filename, file);
 
  xhr.open("POST", action, true);
 
  xhr.withCredentials = withCredentials;
 
  Object.keys(headers).forEach(key => {
    xhr.setRequestHeader(key, headers[key]);
  });
 
  xhr.send(formData);
 
  return xhr;
}