Neo
Neo

Reputation: 2405

Allow antd upload component to show progress bar then remove item after upload

I'm using the ant design uploader component. This all works, however if the file fails to upload for any reason it shows the upload file in red underneath.

What I want to achieve is the file should show while it is uploading (as the progress is shown) then once it has finished, regardles of the outcome (success or fail) it should then not show the file.

I have tried to manipulate the filelist, however when this is set on the component I no longer get the file progress.

Example of what is happening

Upvotes: 2

Views: 5753

Answers (4)

mostafa rastegar
mostafa rastegar

Reputation: 51

in my project, I use fileList and filter by success status in onChange:

...
// add fileLis state and insert to Upload props
const [fileList, setFileList] = useState([]);
...
onChange(info) {
    ...
    // add end of onChange
    setFileList(info.fileList.filter((item) => item.status !== 'success'));
},
...

Depending on how to implement onChange, you can move the codes I have written. But this is how it works. One of my friends also used this method in his answer.

Upvotes: 0

hafizaatifkamal
hafizaatifkamal

Reputation: 1

I got a single-line solution for the problem that shows all the previously uploaded or failed files when the user tries to upload a file. It might not work in all scenarios.

There is a prop called fileList that preserves all the uploaded or unuploaded files. You just need to vacate the content of the fileList array by assigning its length to 0. It worked well for me.

import React from "react";
import { Button, notification, Upload, UploadProps } from "antd";
import { UploadOutlined } from "@ant-design/icons";

const UploadFunc: React.FC = () => {

  const props: UploadProps = {
    name: "file",
    action: `${your_api}/---`,
    
    onChange(info: any) {
      console.log("Before", info.fileList);

      if (info.file.status !== "uploading") {
        let reader = new FileReader();
        reader.onload = (e) => {
          console.log(e.target?.result);
        };
        reader.readAsText(info.file.originFileObj);
      }
      if (info.file.status === "done") {
        info.fileList.length = 0; // this line worked for me
        if (info.file.response.status === "error") {
          notification.error({
            message: `${info.file.name} file couldn't upload! Accounts already exists...`,
          });
        } else {
          notification.success({
            message: `${info.file.name} file uploaded successfully!`,
          });
          
        }
      } else if (info.file.status === "error") {
        info.fileList.length = 0; // // this line worked for me
        notification.error({
          message: `${info.file.name} file upload failed!`,
        });
      }

      console.log("After", info.fileList);
    },
    progress: {
      strokeWidth: 5,
      showInfo: true,
    },
  };

  return (
    <>
      <Upload {...props} accept=".xlsx, .csv" showUploadList={true}>
          <Button type="default" icon={<UploadOutlined />}>
            Upload File
          </Button>
      </Upload>
    </>
  );
};

export default UploadFunc;

I hope this will solve your problem.

Upvotes: 0

Neo
Neo

Reputation: 2405

I managed to work this one out, you have to manipulate the fileList yourself and also handle the upload progress. This is what I came up with...

<Dragger 
    name='CertificateFile' 
    multiple={false} 
    onChange={SingleFileUploadOnChange} 
    customRequest={SingleCertificateFileUploadProcessFile}
    showUploadList={FormState.SingleCertFileUploading}
    fileList={fileList}
>
const [FormState, SetFormState] = useState({
    FormSubmitting: false,
    SingleCertFileUploading: false,
});
     
const [fileList, setFileList] = useState([]);

const SingleFileUploadOnChange = (info) => {
    const FileFound = fileList.some(el => el.name === info.file.name);
    if (!FileFound){
        let NewFileItem = {
            uid: info.file.uid,
            name: info.file.name,
            status: info.file.status,
            percent: 0,
            url: ""
        };
        setFileList(prevState => ([...prevState, NewFileItem]));
    } else {
        // update progress
        const UpdatedFileList = fileList.map(obj => {
            if (obj.name === info.file.name){
                return {...obj, percent: info.file.percent}
            }
        })
        setFileList(UpdatedFileList);
    }

    SetFormState({...FormState, SingleCertFileUploading: true});

    if (['done','error'].includes(info.file.status)){
        var filtered = fileList.filter((el) => { return el.name != info.file.name; }); 
        setFileList(filtered);
    }
}

Upvotes: 1

Ved
Ved

Reputation: 1028

Check the following example

You can set showUploadList to true if it is uploading the file and false if it has uploaded successfully or when file upload fails

import React, { useState } from 'react';
import 'antd/dist/antd.css';
import './index.css';
import { InboxOutlined } from '@ant-design/icons';
import { message, Upload } from 'antd';

const { Dragger } = Upload;

const App = () => {
  const [showupload, setShowupload] = useState(false);

  const props = {
    name: 'file',
    multiple: true,
    action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
    
    onChange(info) {
      setShowupload(true);
      const { status } = info.file;
      if (status !== 'uploading') {
        console.log(info.file, info.fileList);
      }
      if (status === 'done') {
        message.success(`${info.file.name} file uploaded successfully.`);
        setShowupload(false);
      } else if (status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
        setShowupload(false);
      }
    },

    onDrop(e) {
      console.log('Dropped files', e.dataTransfer.files);
    },
  };

  return (
    <Dragger {...props} showUploadList={showupload}>
      <p className="ant-upload-drag-icon">
        <InboxOutlined />
      </p>
      <p className="ant-upload-text">
        Click or drag file to this area to upload
      </p>
    </Dragger>
  );
};

export default App;

Output:

GIF

Upvotes: 2

Related Questions