How can I exchange data between vanilla JavaScript and Flask, receiving CSV as a response via XHR?

I’m having trouble with a data exchange between my frontend and backend. I want to use plain JavaScript’s XMLHttpRequest to send info to my Flask server and get CSV data back as a string. Here’s what I’ve tried:

function sendDataToServer() {
  const xhr = new XMLHttpRequest();
  const token = '{{ csrf_token() }}';
  const payload = { items: [] };
  payload.items.push(someData);

  xhr.onload = () => console.log('Success!');
  xhr.onerror = () => console.error('Request failed');

  xhr.open('POST', '/api/data', true);
  xhr.setRequestHeader('X-CSRFToken', token);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send(payload);
}

My Flask route looks like this:

@app.route('/api/data', methods=['POST'])
def handle_data():
    if request.method == 'POST':
        print(request.form)
        received_data = request.form.get('items')
        # Process data and create CSV
        return csv_content
    else:
        return 'Error', 400

I’m not sure if I can send JSON with the form-urlencoded content type. I’ve tried request.json and request.data on the server side, but no luck. Oddly, it works when I don’t pass any data and just request CSV. Any ideas on how to fix this?

Having worked on similar projects, I can offer some insights. Your approach is close, but there are a few adjustments needed. On the client side, modify your XHR setup to use JSON:

xhr.setRequestHeader(‘Content-Type’, ‘application/json’);
xhr.send(JSON.stringify(payload));

For the Flask route, adjust to handle JSON input:

@app.route(‘/api/data’, methods=[‘POST’])
def handle_data():
if request.is_json:
data = request.get_json()
items = data.get(‘items’)
# Process items and generate CSV
return Response(csv_content, mimetype=‘text/csv’)
return ‘Invalid request’, 400

This should resolve your data exchange issues. Remember to properly handle any potential errors or edge cases in your implementation.

hey, i think i can help. you’re close, but need to tweak a few things. on the JS side, change content type to ‘application/json’ and stringify your payload before sending. in flask, use request.json to grab the data. for sending CSV back, set the right content type in the response. should work like a charm after that!

I’ve dealt with a similar issue before, and I think I see where the problem might be. You’re right to question using ‘application/x-www-form-urlencoded’ for JSON data. Instead, try changing your content type to ‘application/json’ in the JavaScript code.

Also, when sending JSON, you need to stringify your payload:

xhr.setRequestHeader(‘Content-Type’, ‘application/json’);
xhr.send(JSON.stringify(payload));

On the Flask side, you’ll want to use request.json to access the data:

received_data = request.json.get(‘items’)

As for sending CSV back, make sure to set the correct content type in your Flask response:

return csv_content, 200, {‘Content-Type’: ‘text/csv’}

This should allow you to send JSON to the server and receive CSV in return. Hope this helps!