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
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()
}