最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React Antd Upload組件上傳多個(gè)文件實(shí)現(xiàn)方式

 更新時(shí)間:2025年08月30日 10:55:48   作者:水果攤見  
為實(shí)現(xiàn)多文件上傳,需使用beforeUpload和customRequest替代onChange以避免多次調(diào)用問題,并處理文件路徑以兼容Electron不同平臺(tái)

前言

實(shí)現(xiàn)需求:

上傳多個(gè)文件。其實(shí)就是獲取多個(gè)文件的絕對(duì)路徑交給后端接口去處理。

Upload組件

首先,這里不能調(diào)用Upload的onChange函數(shù),因?yàn)樯蟼髦?、完成、失敗都?huì)調(diào)用這個(gè)函數(shù),在多個(gè)文件的情況下會(huì)出現(xiàn)多次調(diào)用問題。

改用beforeUpload和customRequest。

import React, { useRef, useState, useEffect } from 'react';
import { UploadOutlined } from '@ant-design/icons';
import type { UploadFile, UploadProps } from 'antd';
import { Button, Upload } from 'antd';
import { useTranslation } from 'react-i18next';
import Console from '../../../../util/Console';
import { UploadChangeParam } from 'antd/es/upload';
import { sendMsgToMain } from 'electron-prokit';

type Props = {
    name?: string;
    onChangeFilePath: (path: string | null | unknown, info?: UploadChangeParam<UploadFile<any>>) => void;
    accept: Array<string>;
    headers?: any;
    progress?: any;
    buttonTitle?: string;
    rest?: UploadProps;
    action?: string | ((file: any) => Promise<string>);
};

const FileMultiSelectButton: React.FC<Props> = ({
    name,
    onChangeFilePath,
    accept,
    headers,
    progress = null,
    buttonTitle,
    action,
    ...rest
}) => {
    const { t } = useTranslation();
    const fileState: any = useRef();
    const [uploadFiles, setUploadFiles] = useState<UploadFile[]>([]);
    const updateFiles = (function () {
        let fileList: UploadFile[] | null = null;
        return function (list: UploadFile[], setState: React.Dispatch<React.SetStateAction<UploadFile[]>>) {
            if (!fileList) {
                fileList = list;
                setState && setState(list);
            }
            return {
                fileList,
                reset() {
                    fileList = null;
                }
            };
        };
    })();

    const beforeUpload = (_: any, fileList: UploadFile[]) => {
        fileState.current = updateFiles(fileList, setUploadFiles);
        return false;
    }

    const customRequest = () => {
        if (uploadFiles.length > 0) {
            const path = uploadFiles.map(item => (item as any).path);
            // 這是electron的ipc處理函數(shù),在node中復(fù)制文件
            sendMsgToMain({ key: 'fileMultiSelectPath', data: path }).then(filePath => {
                if (typeof onChangeFilePath === 'function') {
                    onChangeFilePath(filePath);
                } else {
                    Console.handleErrorMsg('onChangeFilePath is not a function');
                }
            });
        } else {
            Console.handleWarningMsg('no file uploaded');
        }

    }

    useEffect(() => {
        if (uploadFiles.length > 0) {
            customRequest();
            fileState.current.reset();
        }
    }, [uploadFiles]);

    return (
        <Upload
            name={name || 'file'}
            accept={accept.join(',')}
            progress={progress}
            showUploadList={false}
            headers={headers}
            action={action}
            multiple={true}
            beforeUpload={beforeUpload}
            customRequest={customRequest}
            {...rest}
        >
            <Button icon={<UploadOutlined />}> {buttonTitle || t('Select')} </Button>
        </Upload>
    );
};

export default FileMultiSelectButton;

在node中處理(不必須),這里主要因?yàn)閑lectron需要兼容不同的平臺(tái),需要處理文件路徑

function generateRandomString(length: number) {
    let result = '';
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    const charactersLength = characters.length;
    for (let i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}
const fileSelectPath = (sourcePath: string) => {
    return new Promise((resolve, reject) => {
        const userDataPath = app.getPath('userData');

        // 獲取用戶數(shù)據(jù)目錄,并在該目錄下創(chuàng)建文件夾,用于保存用戶數(shù)據(jù),需要判斷是否存在,如果存在則直接使用,否則創(chuàng)建,并返回該目錄,用于后續(xù)操作,并需要兼容跨平臺(tái),比如windows和mac
        // 拼接出 files 目錄的完整路徑
        const filesDirPath = path.join(userDataPath, 'files');

        fs.mkdir(filesDirPath, { recursive: true }, err => {
            if (err) {
                // 如果目錄創(chuàng)建失敗,返回錯(cuò)誤信息
                // 如果目錄創(chuàng)建失敗,處理錯(cuò)誤
                console.error('Failed to create files directory:', err);
            }

            // 生成一個(gè)隨機(jī)數(shù)
            const randomBytes = generateRandomString(8); // 生成8字節(jié)的隨機(jī)數(shù)

            // 獲取當(dāng)前日期和時(shí)間
            const date = new Date();
            const formattedDate = date.toISOString().split('T')[0].replace(/-/g, ''); // 格式化為不含破折號(hào)的日期
            const formattedTime = date.toTimeString().split(' ')[0].replace(/:/g, ''); // 格式化為不含冒號(hào)的時(shí)間

            // 提取源文件名和擴(kuò)展名
            const { name, ext } = path.parse(sourcePath);

            // 根據(jù)日期、時(shí)間和隨機(jī)數(shù)生成一個(gè)新的文件名
            const newName = `${name}_${formattedDate}_${formattedTime}_${randomBytes}${ext}`;
            // 構(gòu)造目標(biāo)路徑
            const destinationPath = path.join(filesDirPath, newName);

            // 使用fs模塊的copy方法復(fù)制文件
            fs.copyFile(sourcePath, destinationPath, err => {
                if (err) {
                    // 如果文件已存在或復(fù)制失敗,返回錯(cuò)誤信息
                    reject(err);
                } else {
                    // 復(fù)制成功,返回新的文件路徑
                    resolve(destinationPath);
                }
            });
        });
    });
};

export const fileMultiSelectPath = (sourcePath: Array<string>) => {
    return Promise.all(sourcePath.map(async (sourcePath) => {
        return await fileSelectPath(sourcePath);
    }));
};

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • React-Hook中使用useEffect清除定時(shí)器的實(shí)現(xiàn)方法

    React-Hook中使用useEffect清除定時(shí)器的實(shí)現(xiàn)方法

    這篇文章主要介紹了React-Hook中useEffect詳解(使用useEffect清除定時(shí)器),主要介紹了useEffect的功能以及使用方法,還有如何使用他清除定時(shí)器,需要的朋友可以參考下
    2022-11-11
  • React createElement方法使用原理分析介紹

    React createElement方法使用原理分析介紹

    這篇文章主要為大家介紹了React的createElement方法源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • React中的路由嵌套和手動(dòng)實(shí)現(xiàn)路由跳轉(zhuǎn)的方式詳解

    React中的路由嵌套和手動(dòng)實(shí)現(xiàn)路由跳轉(zhuǎn)的方式詳解

    這篇文章主要介紹了React中的路由嵌套和手動(dòng)實(shí)現(xiàn)路由跳轉(zhuǎn)的方式,手動(dòng)路由的跳轉(zhuǎn),主要是通過Link或者NavLink進(jìn)行跳轉(zhuǎn)的,實(shí)際上我們也可以通JavaScript代碼進(jìn)行跳轉(zhuǎn),需要的朋友可以參考下
    2022-11-11
  • React中不適當(dāng)?shù)腍ooks使用問題及解決方案

    React中不適當(dāng)?shù)腍ooks使用問題及解決方案

    在 React 開發(fā)中,Hooks 提供了一種強(qiáng)大的方式來管理組件的狀態(tài)和生命周期,然而,不恰當(dāng)?shù)?nbsp;Hooks 使用可能會(huì)導(dǎo)致組件行為異常、性能問題或難以調(diào)試的錯(cuò)誤,本文將探討 React 中常見的不適當(dāng) Hooks 使用問題,并提供解決方案,需要的朋友可以參考下
    2025-03-03
  • React Draggable插件如何實(shí)現(xiàn)拖拽功能

    React Draggable插件如何實(shí)現(xiàn)拖拽功能

    這篇文章主要介紹了React Draggable插件如何實(shí)現(xiàn)拖拽功能問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 詳解React路由傳參方法匯總記錄

    詳解React路由傳參方法匯總記錄

    這篇文章主要介紹了詳解React路由傳參方法匯總記錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • ReactNative之FlatList的具體使用方法

    ReactNative之FlatList的具體使用方法

    本篇文章主要介紹了ReactNative之FlatList的具體使用方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • 一文帶你搞懂React中的useReducer

    一文帶你搞懂React中的useReducer

    useReducer 是除useState之外另一個(gè)與狀態(tài)管理相關(guān)的 hook,這篇文章主要為大家介紹了useReducer應(yīng)用的相關(guān)知識(shí),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • React Hooks: useEffect()調(diào)用了兩次問題分析

    React Hooks: useEffect()調(diào)用了兩次問題分析

    這篇文章主要為大家介紹了React Hooks: useEffect()調(diào)用了兩次問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • React中react-redux和路由詳解

    React中react-redux和路由詳解

    這篇文章主要介紹了React中react-redux和路由詳解,redux早期被設(shè)計(jì)成可以在各個(gè)框架中使用,因此在不同的框架中使用的時(shí)候,要引入相應(yīng)的插件,感興趣的朋友可以繼續(xù)學(xué)習(xí)下面文章
    2022-08-08

最新評(píng)論

洮南市| 民和| 池州市| 宜春市| 丹阳市| 会同县| 游戏| 甘泉县| 巴林左旗| 镇康县| 武清区| 汪清县| 苍溪县| 大竹县| 嘉义县| 博爱县| 沅陵县| 邵东县| 铅山县| 安乡县| 道孚县| 易门县| 东兰县| 武冈市| 紫金县| 吉安县| 西乌珠穆沁旗| 永川市| 达日县| 海盐县| 龙井市| 榆社县| 遵义县| 宁化县| 石河子市| 自治县| 江山市| 平凉市| 建湖县| 汉中市| 准格尔旗|