Antd - 上传图片 & 裁剪图片

目录

本地上传方法【input type="file"】:

  • js操作本地文件,通过input type="file"选择本地文件

    ts 复制代码
    const fileInput = document.createElement('input');
    fileInput.type = 'file'; // js创建file类型input
    fileInput.click(); // 触发
    fileInput?.addEventListener('change', (event) => {
        const file = event.target?.files[0]; // target返回事件的目标节点,现返回的是input节点本身
        const reader = new FileReader(); // FileReader 只能访问用户明确选择的文件内容
        reader.readAsDataURL(file); // readAsDataURL:开始读取指定的 Blob 中的内容。一旦完成,result 属性中将包含一个表示文件数据的 data: URL
        reader.addEventListener('load', () => {
            console.log(reader.result);
        });
    });
    
    // 用户触发行为点击上传文件
    <input type="file" id="file-input">
    const fileInput = document.getElementById('file-input');
    // 后续同上上传代码

    上传的文件想要不同格式时,可以使用FileReader不同的实例方法获取:

    • readAsArrayBuffer() - 标识文件数据的ArrayBuffer对象

    • readAsBinaryString() - 表示文件中原始二进制数据的字符串

    • readAsDataURL() - 表示文件数据的data:URL

    • readAsText() - 表示所读取的文件内容的字符串,可以制定可选的编码名称

upload组件【antd】

默认接口上传:

  • 使用action属性拼接完整的请求接口地址,eg:action={baseURL + '/v1/object/uploadicon'}
  • 使用默认上传时注意,需要将token携带到请求头属性中

自定义接口上传:【取消默认上传接口】

  • 首先取消默认上传时的接口,在beforeUpload方法return false,来阻止默认上传。即【Upload上传有个action的坑,就是你选择文件之后自动调用地址然后就会执行上传接口,如果不取消会一直有一个失败请求,但不影响主体流程】

  • 上传前文件格式校验

  • 在上传文件校验或onchange方法中获取上传的文件,进行自定义接口请求传递

ts 复制代码
 const props: UploadProps = {
        name: 'file',
        multiple: false,
        showUploadList: false,
       	async beforeUpload(file) {
            setImgLoading(true)
            const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg' || file.type === 'image/webp';
            const isLt2M = file.size / 1024 / 1024 < 2;
            const isSize = await new Promise<boolean>((resolve) => {
                const _URL = window.URL || window.webkitURL;
                const img = new Image();
                img.onload = () => {
                    const valid = img.width / img.height === 1;
                    resolve(valid);
                };
                img.src = _URL.createObjectURL(file);
            });

            if (!isJpgOrPng) {
                message.error('请上传png、jpeg、jpg、webp格式图片');
            } else if (!isLt2M) {
                message.error('上传图片大小不超过2M');
            } else if (!isSize) {
                message.error('上传图片比例建议1:1');
            }
            
            if (!isJpgOrPng || !isLt2M || !isSize) {
                return Upload.LIST_IGNORE;
            }

            return false; // 因为自定义接口请求,没有设置action值,所以关闭默认上传事件
        },
     	onChange(file){
            const files = new FormData();
            files.append('file', file.file);
            // 将files上传给后端接口处理
        }
    };

antd的upload组件beforeUpload还有个比较坑的地方

beforeUpload校验不通过return false的话,onchange中还是会接收到file上传文件信息

解决方法:在beforeUpload校验不通过时return Upload.LIST_IGNORE 阻止文件上传,此时onChange就接收不到不合校验规则的file了

upload结合裁剪

1、antd官方裁剪组件:

裁剪组件是配合 antd-img-crop 实现上传前裁切图片,可以进行属性动态配置

上传前裁剪图片官方使用:

import React, { useState } from 'react';
import { Upload } from 'antd';
import type { GetProp, UploadFile, UploadProps } from 'antd';
import ImgCrop from 'antd-img-crop';

type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];

const App: React.FC = () => {
  const [fileList, setFileList] = useState<UploadFile[]>([
    {
      uid: '-1',
      name: 'image.png',
      status: 'done',
      url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
    },
  ]);

  const onChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
    setFileList(newFileList);
  };

  const onPreview = async (file: UploadFile) => {
    let src = file.url as string;
    if (!src) {
      src = await new Promise((resolve) => {
        const reader = new FileReader();
        reader.readAsDataURL(file.originFileObj as FileType);
        reader.onload = () => resolve(reader.result as string);
      });
    }
    const image = new Image();
    image.src = src;
    const imgWindow = window.open(src);
    imgWindow?.document.write(image.outerHTML);
  };

  return (
    <ImgCrop rotationSlider>
      <Upload
        action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
        listType="picture-card"
        fileList={fileList}
        onChange={onChange}
        onPreview={onPreview}
      >
        {fileList.length < 5 && '+ Upload'}
      </Upload>
    </ImgCrop>
  );
};

export default App;

2、antd裁剪图片二次开发

antd官方提供的裁剪可以设置裁剪的比例、形状,放大缩小、旋转按钮显隐等,但一般实际开发时需求与官方例子会略有差异,需要进行裁剪组件源码理解以及二次开发

开发需求要求(重新上传、任务对比框、重新打开裁剪框等):

将antd封装的官方裁剪组件代码拉取到项目中进行再次开发

组件源码目录

具体的二次开发步骤后续更新 ~

结合form表单使用:

上传图片结合form表单使用时,页面的图片字段检测不到Upload上传图片获取的url数据变化导致图片更新问题,如何实现检测数据变化

有不对的地方请大佬们指正 ^^

相关推荐
小行星1251 分钟前
前端把dom页面转为pdf文件下载和弹窗预览
前端·javascript·vue.js·pdf
Lysun00110 分钟前
[less] Operation on an invalid type
前端·vue·less·sass·scss
J总裁的小芒果26 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
Lei_zhen9628 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
咖喱鱼蛋31 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder32 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
鑫宝Code1 小时前
【React】React Router:深入理解前端路由的工作原理
前端·react.js·前端框架
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
永乐春秋3 小时前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿3 小时前
【前端】CSS
前端·css