3

I am having trouble writing a program for sending html form using an ajax call in jQuery. Here is my upload.html and form.js file:

$(document).ready(function() {

	$('form').on('submit', function(event) {

		$.ajax({
			type : 'POST',
			url : '/uploadhc',
			data : $('#hc')
		})
		.done(function(data) {

			if (data.error) {
				$('#errorAlert').text(data.error).show();
				$('#successAlert').hide();
			}
			else {
				$('#successAlert').text(data.file).show();
				$('#errorAlert').hide();
			}

		});

		event.preventDefault();

	});

});
<!DOCTYPE html>
<html lang="en">
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <meta charset="UTF-8">
    <title>File Upload</title>
    <script type=text/javascript src="{{ url_for('static', filename='form.js') }}"></script>
</head>
<body>
<h1>Please upload all the corresponding files</h1>
<div id="upload">
    <form id="upload-hc" >
        <input type="file" name="file" accept=".csv" id="hc">
        <input type="submit" value="go">
    </form>
    <br>
    <p id="successAlert" style="display:none;">Success!</p>
	<p id="errorAlert" style="display:none;">Fail!</p>


</div>

<script>

</script>

</body>
</html>

Here is my Flask server:

import os
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)
APP_ROOT = os.path.dirname(os.path.abspath(__file__))

@app.route("/")
def index():
    return render_template("upload.html")


@app.route("/uploadhc", methods=['POST'])
def uploadhc():
    target = os.path.join(APP_ROOT, "DataSource/")


    if not os.path.isdir(target):
        os.mkdir(target)
    print request.files
    if 'file' not in request.files:
        error = "Missing data source!"
        return jsonify({'error': error})


    file = request.files['file']
    fileName = "DCData.csv"
    destination = '/'.join([target, fileName])
    file.save(destination)


    success = "Success!"
    return jsonify({'file': success})


if __name__ == "__main__":
    app.run(port=4555, debug=True)

When I try to select a csv file and submit the HTML form, the server says the request.files is ImmutableMultiDict([]), which is empty. Any idea how to send the file to my server? Thanks!

3 Answers 3

4

You need to send the form as multipart upload, you can transform the entier form to that with FormData(formElement)

var form = $('#upload-hc')[0]
var fd = new FormData(form)

$.ajax({
  type : 'POST',
  url : '/uploadhc',
  data: fd,
  processData: false,  // tell jQuery not to process the data
  contentType: false   // tell jQuery not to set contentType
})

Here you got a es6 version if you would be interested

// short for jquery(function($){ ... })
// which is the equvilant to $(document).ready(function($) {
jQuery($ => {
  
  $('form').on('submit', event => {
    event.preventDefault()
    
    let form = $('#upload-hc')[0]
    let fd = new FormData(form)

    fetch('/uploadhc', {method: 'POST', body: fd})
    .then(res => {
      // console.log(res.ok)
      return res.json() // or res.text, res.arraybuffer
    })
    .then(result => {
      console.log(result)
    })
  })
  
})

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! I tried FormData([formElement]), but the ImmutableMultiDict([]) is still empty
Did you try it without the []?
Yeah. But my server still cannot get the form data
3

In the html side:

<input type="file" id="uploadfile" name="NewCsvUpload">

In the javascript side:

var form_data = new FormData();
form_data.append('file', $('#uploadfile').prop('files')[0]);

$(function() {
$.ajax({
    type: 'POST',
    url:  '/uploadLabel',
    data: form_data,
    contentType: false,
    cache: false,
    processData: false,
    success: function(data) {
        console.log('Success!');
    },
  })
});

In the server side:

@app.route('/uploadLabel',methods=[ "GET",'POST'])
def uploadLabel():
    isthisFile=request.files.get('file')
    print(isthisFile)
    print(isthisFile.filename)
    isthisFile.save("./"+isthisFile.filename)

Comments

-1

When I've done this in the past, I've always put enctype="multipart/form-data" in the form div.

Here a couple of links that explain it in further detail:

1 Comment

Yeah. But I don't think adding the 'enctype' is helping here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.