I've created an API for my React site to get/upload images using fetch
.
It's working for PC and Android phones, didn't bother to check Safari until the users said they cant do it on iPhones/iPads.
Plugged in the macbook and saw i was getting CORS errors when uploading a file:
Origin https://xxxxxxx is not allowed by Access-Control-Allow-Origin
Funny thing is, when the page loads, it's calling the same API to retrieve existing images, and that works fine. My API is PHP, i've already added lines at the top:
header("Access-Control-Allow-Origin: https://xxxxxxx");
header("Access-Control-Allow-Methods: POST, OPTIONS");
header("Access-Control-Allow-Headers: X-Requested-With, Accept, Content-Type, Origin, Content-Length, Accept-Language, Host, User-Agent, Referer, Accept-Encoding, Connection");
The infra guys swear they've opened up their WAF to allow uploads (i believe them because the PC/Android phones work)
I've tried using Chrome on the iPhone but that doesn't work either.
All the fetches run through this:
const API_URL = 'api_url';
const customFetcher = async (formData) => {
let response = fetch(API_URL, {
method: 'POST',
body: formData,
mode: 'cors'
})
.then(r => {
console.log('custom', r.status);
if (r.status === 205) {
throw new Error('Session expired');
} else {
return r;
}
});
return response;
}
export default customFetcher;
The upload fetch that throws the CORS error:
let formData = new FormData();
formData.append('auth', this.props.user.state.token);
formData.append('key', 'le_key')
formData.append('what', 'upload');
formData.append('userId', this.props.user.state.userId);
formData.append('serialNo', this.state.serialNo + '|' + this.state.firstName + '|' + this.state.lastName)
formData.append('photo', this.state.selectedFiles[0]);
customFetcher(formData)
...
The fetch to retrieve existing images:
let formData = new FormData();
formData.append('auth', this.props.user.state.token);
formData.append('key', 'le_key')
formData.append('what', 'photo');
formData.append('userId', this.props.user.state.userId);
formData.append('serialNo', this.state.serialNo + '|' + this.state.firstName + '|' + this.state.lastName);
customFetcher(formData)
.then(r => {
if (r.status !== 404) {
return r.blob();
} else {
this._setNoImage();
return false;
}
})
PROGRESS: OK, found out it works if i take a fresh photo from the file input! Meaning its been sending an empty file which causes this error if i select from the file browser.
So the question now is how am i able to grab that selected file? I do this:
<FormControl
type="file"
onChange={this._updateFile}
/>
_updateFile = (e) => {
this.setState({
selectedFiles: e.target.files[0]
})
}
I've even tried to check the file size but its good, somehow still sending nothing. Any ideas? TIA