How should customRequest be set in the Ant Design Upload component to work with an XMLHttpRequest? How should customRequest be set in the Ant Design Upload component to work with an XMLHttpRequest? reactjs reactjs

How should customRequest be set in the Ant Design Upload component to work with an XMLHttpRequest?


I was struggling with that as well and then I found your question.

So the way I found to use customRequest and onChange is:

    <Upload name="file" customRequest={this.customRequest} onChange={this.onChange}>      <Button>        <Icon type="upload" /> Click to Upload      </Button>    </Upload>  ...  onChange = (info) => {    const reader = new FileReader();    reader.onloadend = (obj) => {      this.imageDataAsURL = obj.srcElement.result;    };    reader.readAsDataURL(info.file.originFileObj);    ...  };  ...  customRequest = ({ onSuccess, onError, file }) => {    const checkInfo = () => {      setTimeout(() => {        if (!this.imageDataAsURL) {          checkInfo();        } else {          this.uploadFile(file)            .then(() => {              onSuccess(null, file);            })            .catch(() => {              // call onError();            });        }      }, 100);    };    checkInfo();  };

There are probably better ways to do it, but I hope that helps you.


I struggled it a lot and find an efficient way to handle this case.

first- you should mess with the customRequest only when you need to change to body and the request type (like using post instead of 'put' or using xml or add another extra header).

for the signing Url you can send in the action prop callback which return a promise with the right Url to upload like:

 handleUplaod = (file: any) => {return new Promise(async (resolve, reject) => {  const fileName = `nameThatIwant.type`;  const url = await S3Fetcher.getPresignedUrl(fileName);  resolve(url);});

and render like:

render(){    return(    ....    <Upload    action={this.handleUplaod}    .... Upload>

the uploader take the url from the action prop.

the onChange method which is provided also will be called any time the status of upload is changed-

onChange# The function will be called when uploading is in progress, completed or failed.

When uploading state change, it returns:

{ file: { /* ... / }, fileList: [ / ... / ], event: { / ... */ }, }

when upload startedyou will need to activate the file reader from that.like:

.... fileReader = new FileReader(); .....onChange = (info) => {    if (!this.fileReader.onloadend) {      this.fileReader.onloadend = (obj) => {        this.setState({          image: obj.srcElement.result, //will be used for knowing load is finished.        });      };    // can be any other read function ( any reading function from    // previously created instance can be used )    this.fileReader.readAsArrayBuffer(info.file.originFileObj);    }  };

notice when completed stage that event=undefind

To update the UI from the upload events you should use the options variables from customRequest and call them whenever you need.

onSuccess- should be called when you finish uploading and it will change the loading icon to the file name.

onError- will paint the file name filed to red.

onProgress- will update the progress bar and should be called with {percent: [NUMBER]} for updating.

for example in my code-

customRequest = async option => {  const { onSuccess, onError, file, action, onProgress } = option;  const url = action;  await new Promise(resolve => this.waitUntilImageLoaded(resolve)); //in the next section   const { image } = this.state; // from onChange function above  const type = 'image/png';  axios    .put(url, Image, {      onUploadProgress: e => {        onProgress({ percent: (e.loaded / e.total) * 100 });      },      headers: {        'Content-Type': type,      },    })    .then(respones => {      /*......*/      onSuccess(respones.body);    })    .catch(err => {      /*......*/      onError(err);    });}; waitUntilImageLoaded = resolve => {  setTimeout(() => {    this.state.image      ? resolve() // from onChange method      : this.waitUntilImageLoaded(resolve);  }, 10);};

I used axios but you can use other libraries as welland the most important part-

render(){return(....<UploadonChange={this.onChange} customRequest={this.customRequest}...>


  onCustomRequest = file => {    return new Promise(((resolve, reject) => {      const ajaxResponseWasFine = true;      setTimeout(() => {        if (ajaxResponseWasFine) {          const reader  = new FileReader();          reader.addEventListener('load', () => {            resolve(reader.result);          }, false);          if (file) {            reader.readAsDataURL(file);          }        } else {          reject('error');        }      }, 1000);    }));  };        <Dragger          action={this.onCustomRequest}          fileList={fileList}          onChange={this.handleChangeUpload}          className={styles.dragWrapper}          showUploadList={true}          beforeUpload={this.beforeUpload}        >