Cancel File Upload Post request using Axios

I am trying to implement a cancel function to cancel a file upload of a video while it's uploading. This is what my front-end looks like while the video is uploading

enter image description here

Here is my code for the post request using axios:

export function processPost (body, callback, errorUpdate) {
// config for post
var config = {
  timeout: 300000,
  headers: { 'content-type': 'multipart/form-data' }

}

// url for server endpoint
var url = 'http://localhost:5000/uploader'

// actual post
axios
  .post(url, body, config)
  .then(callback)
  .catch(function (error) {
    // Non 200 Response
    if (error.response) {
      errorUpdate('non 200 response from server')
      // Request made but no response received
    } else if (error.request) {
      errorUpdate('no response from server')
      // something else happened
    } else {
      errorUpdate('Something Else Happened')
    }
    throw error
  })
}

And here's the code for the front-end:

export default class Welcome extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      state: 'PENDING',
      selectedFile: null
    }
    this.handleClick = this.handleClick.bind(this)
    this.post = this.post.bind(this)
  }

  handleClick () {
    if (this.state.state === 'PENDING') {
      this.refs.fileUploader.click()
    } else {
      cancelPost()
      this.setState({ state: 'PENDING' })
    }
  }

  handleChange (selectorFiles) {
    if (selectorFiles.length === 0) return
    console.log(selectorFiles)
    this.post(selectorFiles[0])
  }

  post (file) {
    // set screen to loading
    this.setState({
      state: 'PROCESSING',
      selectedFile: file
    })

    // set up body
    const data = new FormData()
    data.append('file', file)

    // pass in header, body, then callback
    processPost(data,
      resp => {
        console.log(resp.data)
        this.props.successfulPost(file, URL.createObjectURL(file), resp.data.boardTranscription, resp.data.audioTranscription)
      },
      error => {
        // if there is an error, log it and reset state
        console.log(error)
        this.setState({ state: 'PENDING' })
      })
  }

  render () {
    var jumboClass = classNames({
      'jumbotron col-8 offset-2 light-pink text-center': true,
      'jumboProcessing': this.state.state === 'PROCESSING'
    })

    var input
    var loading
    if (this.state.state === 'PROCESSING') {
      input = null
      loading = (
        <div>
          <div className="spinner-border" role="status">
            <span className="sr-only">Loading...</span>
          </div>
          <p>processing {this.state.selectedFile.name} ...</p>
          <button className={'btn btn-outline-light'} onClick={this.handleChange('')}>Cancel</button>
        </div>
      )
    } else {
      input = (
        <React.Fragment>
          <br></br>
          <button
            className={'btn-light btn-lg'}
            onClick={this.handleClick}
          >Upload Video</button>
          <input id="file" ref="fileUploader" type="file" accept='video/*'
            style={{ display: 'none' }}
            onChange={ (e) => this.handleChange(e.target.files) } />
        </React.Fragment>
      )
      loading = null
    }
    return (
      <div className={'row vertical-center'}>
        <div className={jumboClass}>
          <h2 className={'h2 font-size:10vw'}>Welcome to AutoNote!</h2>
          <h6 className={'h6 font-size:5vw'}>Upload a video to generate a linked transcription.</h6>
          {input}
          <br></br>
          {loading}
        </div>
      </div>)
  }
}

Welcome.propsType = {
  successfulPost: PropTypes.function
}

How would i go about implementing the cancellation functionality within Axios so that when the user clicks on the "cancel" button, the post request will be cancelled? Any help is much appreciated. Thank you!


You need to make use of CancelToken.

Basically, you need to pass a canceltoken in the config object while using axios.post and when you want to cancel, you can call cancel function.

Example:

let cancelTokenSource = axios.CancelToken.source();

then, in the request config object, pass the token as cancelToken say :

config = { ...otherConfigs, cancelToken : cancelTokenSource.token }

So now, we can use

 cancelTokenSource.cancel('Upload cancelled');

to cancel wherever you want say, upon clicking some cancel button.


I think it should be done this way:

You will first have to create a cancel token as shown below and add it before your axios post request

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

then add cancelToken: source.token to your axios config

var config = {
    /* ... */
    cancelToken: source.token,
}

now you have to store source in a state, so put this after your axios post

this.setState({source});

finally create a handleCancel() method and call it when user clicked on the cancel button

handleCancel() {
    this.state.source.cancel()
}