I'm trying to upload a file to a Django server using Axios post requests in a React app. The server expects a CSRF cookie in the request header.
This request already contains all the methods I can find for setting cookies. Pass document.cookie
, set withCredential: true
, and specify the Cookie
header.
This is my Axios request:
const onSubmit = async (data) => { const formData = new FormData() formData.append('file', data.file[0]) const csrftoken = getCookie('csrftoken'); document.cookie = `csrftoken=${csrftoken}` const res = await axiosInstance.post('/upload/', formData, { timeout: 0, headers: { 'Cookie': `csrftoken=${csrftoken}`, 'Content-Type': 'multipart/form-data', 'x-csrftoken': csrftoken, }, withCredentials: true, }) console.log(res) }
This is my Django view:
def upload_file(request): form = UploadFileForm() if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): file_id = save_file_to_database(request.FILES['file']) response = JsonResponse({'id': file_id}, status=201) return response else: response = HttpResponse({'message': 'Upload failed'}, status=400) return response return render(request, 'upload.html', {'form': form})
Also, I believe I have the relevant Django settings set correctly in settings.py
:
CORS_ORIGIN_WHITELIST = ( "http://localhost:8000", "http://127.0.0.1:5173", ) CSRF_TRUSTED_ORIGINS = [ "http://127.0.0.1:5173" ] SESSION_COOKIE_SAMESITE = 'None'
How do I ensure that the CSRF cookie is included in the request header or otherwise meets CSRF requirements? To be sure, the route works if we add @csrf_exempt
to the view, so it really should be a CSRF issue.
P粉4638244102024-03-29 10:02:40
You just need to include the token in formData
. No header or cookie manipulation required:
const onSubmit = async (data) => { const formData = new FormData() formData.append('file', data.file[0]) formData.append('csrfmiddlewaretoken', getCookie('csrftoken')); const res = await axiosInstance.post('/upload/', formData, { timeout: 0, headers: { 'Content-Type': 'multipart/form-data', }, withCredentials: true, }) console.log(res) }
Tip: Whenever you are unsure whether cookies, headers, etc. are being sent, check the Network tab in your browser's developer tools. If you see them in the Request Headers section of the request, then they are being sent, which means the problem is on the server side. In this case, for multipart/form-data Django requires the csrfmiddlewaretoken
token in the form field. For application/json
requests, you can use the X-CSRFToken
header.