• 整个组件功能代码-->图片压缩上传&&axios封装


    // 项目中上传图片组件 and其它功能
    import React, { useState, useRef } from 'react';
    import { QrcodeOutlined } from '@ant-design/icons';
    import '@ant-design/compatible/assets/index.css';
    import { Modal, Button, message } from 'antd';
    import { useObserver } from 'mobx-react';
    import { useHistory, useLocation } from 'react-router-dom';
    // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
    // @ts-ignore
    import QRCode from 'qrcode';
    import ajax from '@/lib/axios';
    import { Wrapper, SuccessWrapper, UploadImgWrapper } from './link-qrcode-style';
    
    interface IProps {
      merchantId: string;
      branchName: string;
      merchantName: string;
      personInCharge: string;
    }
    
    const LinkQrCode = (props: IProps) => {
      const [showConfirmModal, setShowConfirmModal] = useState<boolean>(false);
      const [showSuccessModal, setShowSuccessModal] = useState<boolean>(false);
      const [showUploadModal, setShowUploadModal] = useState<boolean>(false);
      const [uploadButtonLoading, setUploadButtonLoading] = useState<boolean>(false);
      const [confirmButtonLoading, setConfirmButtonLoading] = useState<boolean>(false);
      const [qrCodeUrl, setQrCodeUrl] = useState<string>('');
      const [qrDecode, setQrDecode] = useState<string>('');
      const [uploadImgUrl, setUploadImgUrl] = useState<string>('');
      const [canvasToBlob, setCanvasToBlob] = useState<any>({});
      const history = useHistory();
      const location = useLocation();
      const fileInputRef = useRef<HTMLInputElement>(null);
      // const ua = navigator.userAgent.toLowerCase();
      // const isIos = ua.indexOf('iphone') !== -1 || ua.indexOf('ipad') !== -1;
    
      const uploadFileValidate = async () => {
        try {
          const makeBoundary = function() {
            return '----JQBoundary' + btoa(Math.random().toString()).substr(0, 12);
          };
          const boundary = makeBoundary();
          const formData = new FormData();
        
    // 这里需要注意,formdata.append()括号里参数的名称是根据后端定的,不是固定的.
    后端需要什么字端,就append什么字段,如果需要多个字段,就写多个append()
          formData.append('qrcodeImage', canvasToBlob);
          const {
            data: { data },
          } = await ajax.post('/qrcode/validate', formData, {
         
    // 请求后端上传接口的方法中,参数直接是上面封装的formdata即可,不需要其它。
    // 另外请求默认的content-type是application/json,上传文件接口这里需要自己定义content-type:multipart/form-data。
    定义了content-type之后需要手动添加boundary,否则会报错。
            headers: { 'Content-Type': `multipart/form-data; boundary=${boundary}` },
          });
          setUploadButtonLoading(false);
          setShowUploadModal(false);
          if (data) {
            setQrDecode(data);
            setShowConfirmModal(true);
          } else {
            Modal.error({
              content: "Sorry, we can't process this picture, please make sure you use a clear picture of valid QR code.",
              onOk() {
                const to = `${location.pathname}${location.search}`;
                history.push(to);
              },
            });
          }
        } catch (e) {
          message.error(e.message);
        }
      };
    
      const qrCodeUploadedHandler = (imageFile: object, fileImageUrl: string) => {
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d') as any;
        const img = new Image();
        img.src = fileImageUrl;
        img.onload = () => {
          const originWidth = img.width;
          const originHeight = img.height;
          const maxWidth = 1280;
          const maxHeight = 768;
          let targetWidth = originWidth;
          let targetHeight = originHeight;
          if (originWidth > maxWidth || originHeight > maxHeight) {
            if (originWidth / originHeight > maxWidth / maxHeight) {
              // 更宽,按照宽度限定尺寸
              targetWidth = maxWidth;
              targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
              targetHeight = maxHeight;
              targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
          }
          // canvas对图片进行缩放
          canvas.width = targetWidth;
          canvas.height = targetHeight;
          // 清除画布
          context.clearRect(0, 0, targetWidth, targetHeight);
          // 图片压缩
          context.drawImage(img, 0, 0, targetWidth, targetHeight);
          canvas.toBlob(
            blob => {
              // const newImage = new File([blob as any], (imageFile as any).name, { type: (imageFile as any).type });
              setCanvasToBlob(blob);
            },
            'image/jpeg',
            0.7,
          );
        };
        img.onerror = () => console.error('Upload file of image format please.');
      };
    
      const handleUploadButton = (e: React.MouseEvent) => {
        e.preventDefault();
        setUploadButtonLoading(true);
        uploadFileValidate();
      };
    
      const handleFileChange = (e: any) => {
        const file = e.target.files[0];
        if (file !== undefined) {
          const fr = new FileReader();
          fr.readAsDataURL(file);
          fr.addEventListener('load', () => {
            setUploadImgUrl(fr.result as string); //base64
            qrCodeUploadedHandler(file, fr.result as string);
            setShowUploadModal(true);
          });
        } else {
          setUploadImgUrl('');
        }
      };
    
      const backToListPage = () => {
        const to = `${location.pathname}${location.search}`;
        history.push(to);
      };
    
      const handleLinkButton = (e: React.MouseEvent) => {
        e.preventDefault();
        if (!!fileInputRef) {
          (fileInputRef as any).current.click();
        }
      };
    
      const handleConfirmLink = async (e: React.MouseEvent) => {
        e.preventDefault();
        setConfirmButtonLoading(true);
        try {
          const {
            data: { data },
          } = await ajax.post('/qrcode/bind', { qrcode: qrDecode, bindObjectId: props.merchantId });
          if (data.length > 0) {
            try {
              const codeUrl = await QRCode.toDataURL(data[0]);
              setQrCodeUrl(codeUrl);
            } catch (err) {
              console.error(err);
            }
            setConfirmButtonLoading(false);
            setShowConfirmModal(false);
            setShowSuccessModal(true);
          }
        } catch (e) {
          message.error(e.message);
        }
      };
    
      const handleConfirmModalCancel = (e: React.MouseEvent) => {
        e.preventDefault();
        setShowConfirmModal(false);
        backToListPage();
      };
    
      const handleSuccessModalCancel = (e: React.MouseEvent) => {
        e.preventDefault();
        setShowSuccessModal(false);
        backToListPage();
      };
    
      return useObserver(() => (
        <>
          <div>
            <Button onClick={handleLinkButton} style={{  '100%', marginTop: 5 }} type="default" size="small">
              <QrcodeOutlined />
              Link QR code
            </Button>
            <input
              type="file"
              name="cover"
              accept="image/*"
              ref={fileInputRef}
              style={{  0, height: 0 }}
              onChange={handleFileChange}
            />
          </div>
          <Modal
            destroyOnClose={true}
            title="Confirm Information"
            visible={showConfirmModal}
            style={{ top: 20 }}
            width={'80%'}
            maskClosable={false}
            footer={[
              <Button
                type="primary"
                key="confirm"
                style={{ fontSize: '30px', height: '60px' }}
                loading={confirmButtonLoading}
                htmlType="button"
                onClick={handleConfirmLink}>
                Confirm
              </Button>,
              <Button
                key="cancel"
                htmlType="button"
                style={{ fontSize: '30px', height: '60px' }}
                onClick={handleConfirmModalCancel}>
                Cancel
              </Button>,
            ]}
            onCancel={handleConfirmModalCancel}>
            <Wrapper>
              <p>
                {/* eslint-disable-next-line react/no-unescaped-entities */}
                You're linking the QR code you scaned to the following merchant. Please check the merchant information
                throughly.
              </p>
              <div className="confirm-information">
                <div className="confirm-information-item">
                  <span>Merchant ID:</span>
                  <p>{props.merchantId}</p>
                </div>
                <div className="confirm-information-item">
                  <span>Branch Name:</span>
                  <p>{props.branchName}</p>
                </div>
                <div className="confirm-information-item">
                  <span>Merchant Name:</span>
                  <p>{props.merchantName}</p>
                </div>
                <div className="confirm-information-item">
                  <span>Person in Charge:</span>
                  <p>{props.personInCharge}</p>
                </div>
              </div>
            </Wrapper>
          </Modal>
          <Modal
            destroyOnClose={true}
            visible={showSuccessModal}
            style={{ top: 20 }}
            width={'50%'}
            maskClosable={false}
            footer={null}
            onCancel={handleSuccessModalCancel}>
            <SuccessWrapper>
              <p className="top-tip">QR code has been successfully linked!</p>
              <div className="branch-name">
                <span>Branch Name:</span>
                <p>{props.branchName}</p>
              </div>
              <div className="qr-code">
                <span>QR Code:</span>
                <img src={qrCodeUrl} alt="图片加载失败" />
              </div>
            </SuccessWrapper>
          </Modal>
          <Modal
            destroyOnClose={true}
            visible={showUploadModal}
            style={{ top: 20, textAlign: 'center' }}
            width={'80%'}
            maskClosable={false}
            closable={false}
            footer={null}>
            <UploadImgWrapper>
              <img id="img" src={uploadImgUrl} style={{  '90%' }} alt="" />
            </UploadImgWrapper>
            <Button
              type="primary"
              key="confirm"
              loading={uploadButtonLoading}
              size="large"
              htmlType="button"
              style={{ margin: '20px',  '90%', fontSize: '30px', height: '60px' }}
              onClick={handleUploadButton}>
              UPLOAD
            </Button>
          </Modal>
        </>
      ));
    };
    
    export default LinkQrCode;
    // axios封装
    import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, Canceler } from 'axios';
    import Cookies from 'js-cookie';
    import { message } from 'antd';
    
    export let cancel!: Canceler;
    export const ROUTE_CHANGE = 'ROUTE_CHANGE';
    
    export const handleError = (e: AxiosError) => {
      message.error(`CODE: ${e.code}
     MESSAGE: ${e.message}`);
    };
    
    const requestInterceptor = (config: AxiosRequestConfig) => {
      const acceptLanguages = [...navigator.languages];
    // config.headers['Authorization'] = xxx,这种方式写法只会重写
    // headers中Authorization字段,不会重写整个headers.
    // 如果config.headers= {xxx},每次请求的headers都会被重写成这里定义
    // 的,会导致你在调请求方法时手动指定的headers失效。
      config.headers['Authorization'] = Cookies.get('token');
      config.headers['Accept-Language'] = acceptLanguages.join(',');
      return config;
    };
    
    const responseInterceptor = (res: AxiosResponse) => {
      if (res.data.code !== 'SUCCESS') {
        throw {
          isAxiosError: false,
          request: res.request,
          name: res.data.code,
          config: res.config,
          code: res.data.code,
          message: res.data.message,
          response: res,
        } as AxiosError;
      } else {
        return res;
      }
    };
    
    const ajax = axios.create({
      baseURL: '/api',
      timeout: 60000,
    });
    
    ajax.interceptors.response.use(responseInterceptor);
    ajax.interceptors.request.use(requestInterceptor);
    
    export default ajax;
    // AxiosRequestConfig  ===> ts
    export interface AxiosTransformer {
      (data: any, headers?: any): any;
    }
    
    export interface AxiosAdapter {
      (config: AxiosRequestConfig): AxiosPromise<any>;
    }
    
    export interface AxiosBasicCredentials {
      username: string;
      password: string;
    }
    
    export interface AxiosProxyConfig {
      host: string;
      port: number;
      auth?: {
        username: string;
        password:string;
      };
      protocol?: string;
    }
    
    export type Method =
      | 'get' | 'GET'
      | 'delete' | 'DELETE'
      | 'head' | 'HEAD'
      | 'options' | 'OPTIONS'
      | 'post' | 'POST'
      | 'put' | 'PUT'
      | 'patch' | 'PATCH'
      | 'link' | 'LINK'
      | 'unlink' | 'UNLINK'
    
    export type ResponseType = 
      | 'arraybuffer' 
      | 'blob' 
      | 'document' 
      | 'json' 
      | 'text' 
      | 'stream'
    
    export interface AxiosRequestConfig {
      url?: string;
      method?: Method;
      baseURL?: string;
      transformRequest?: AxiosTransformer | AxiosTransformer[];
      transformResponse?: AxiosTransformer | AxiosTransformer[];
      headers?: any;
      params?: any;
      paramsSerializer?: (params: any) => string;
      data?: any;
      timeout?: number;
      timeoutErrorMessage?: string;
      withCredentials?: boolean;
      adapter?: AxiosAdapter;
      auth?: AxiosBasicCredentials;
      responseType?: ResponseType;
      xsrfCookieName?: string;
      xsrfHeaderName?: string;
      onUploadProgress?: (progressEvent: any) => void;
      onDownloadProgress?: (progressEvent: any) => void;
      maxContentLength?: number;
      validateStatus?: (status: number) => boolean;
      maxRedirects?: number;
      socketPath?: string | null;
      httpAgent?: any;
      httpsAgent?: any;
      proxy?: AxiosProxyConfig | false;
      cancelToken?: CancelToken;
    }
    
    export interface AxiosResponse<T = any>  {
      data: T;
      status: number;
      statusText: string;
      headers: any;
      config: AxiosRequestConfig;
      request?: any;
    }
    
    export interface AxiosError<T = any> extends Error {
      config: AxiosRequestConfig;
      code?: string;
      request?: any;
      response?: AxiosResponse<T>;
      isAxiosError: boolean;
      toJSON: () => object;
    }
    
    export interface AxiosPromise<T = any> extends Promise<AxiosResponse<T>> {
    }
    
    export interface CancelStatic {
      new (message?: string): Cancel;
    }
    
    export interface Cancel {
      message: string;
    }
    
    export interface Canceler {
      (message?: string): void;
    }
    
    export interface CancelTokenStatic {
      new (executor: (cancel: Canceler) => void): CancelToken;
      source(): CancelTokenSource;
    }
    
    export interface CancelToken {
      promise: Promise<Cancel>;
      reason?: Cancel;
      throwIfRequested(): void;
    }
    
    export interface CancelTokenSource {
      token: CancelToken;
      cancel: Canceler;
    }
    
    export interface AxiosInterceptorManager<V> {
      use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: any) => any): number;
      eject(id: number): void;
    }
    
    export interface AxiosInstance {
      (config: AxiosRequestConfig): AxiosPromise;
      (url: string, config?: AxiosRequestConfig): AxiosPromise;
      defaults: AxiosRequestConfig;
      interceptors: {
        request: AxiosInterceptorManager<AxiosRequestConfig>;
        response: AxiosInterceptorManager<AxiosResponse>;
      };
      getUri(config?: AxiosRequestConfig): string;
      request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
      get<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
      delete<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
      head<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
      options<T = any, R = AxiosResponse<T>>(url: string, config?: AxiosRequestConfig): Promise<R>;
      post<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
      put<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
      patch<T = any, R = AxiosResponse<T>>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R>;
    }
    
    export interface AxiosStatic extends AxiosInstance {
      create(config?: AxiosRequestConfig): AxiosInstance;
      Cancel: CancelStatic;
      CancelToken: CancelTokenStatic;
      isCancel(value: any): boolean;
      all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
      spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
    }
    
    declare const Axios: AxiosStatic;
    
    export default Axios;
  • 相关阅读:
    codeforces 673D D. Bear and Two Paths(构造)
    codeforces 673C C. Bear and Colors(暴力)
    codeforces 673B B. Problems for Round(模拟)
    codeforces 673A A. Bear and Game(水题)
    hdu-3555 Bomb(数位dp)
    西交校赛 I. GZP and CS(数位dp)
    西交校赛 F. GZP and Poker
    删除目录下包含“2018” 关键字文件
    CSV转成Excel格式
    解决字符sqlplus 乱码
  • 原文地址:https://www.cnblogs.com/chenbeibei520/p/12551970.html
Copyright © 2020-2023  润新知