DIRECTIONNZ
DIRECTIONNZ

Reputation: 63

File upload using Flask and jQuery

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!

Upvotes: 3

Views: 7602

Answers (3)

蘇韋文
蘇韋文

Reputation: 121

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)

Upvotes: 3

Endless
Endless

Reputation: 37786

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

Upvotes: 4

TheF1rstPancake
TheF1rstPancake

Reputation: 2378

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:

Upvotes: -1

Related Questions