34

Hi I'm quite new to flask and I want to upload a file using an ajax call to the server. As mentioned in the documentation, I added a file upload to the html as folows:

<form action="" method=post enctype="multipart/form-data" id="testid">
 <table>
  <tr>
   <td>
     <label>Upload</label>
   </td>
   <td>
     <input id="upload_content_id" type="file" name="upload_file" multiple>
     <input type="button" name="btn_uplpad" id="btn_upload_id" class="btn-upload" value="Upload"/>

   </td>
  </tr>
 </table>
</form>

and I wrote the ajax handler as this

$(document).ready(function() {
    $("#btn_upload_id" ).click(function() {           
        $.ajax({
            type : "POST",
            url : "/uploadajax",
            cache: false,
            async: false,
            success : function (data) {},
            error: function (XMLHttpRequest, textStatus, errorThrown) {}
        });
    });
});

I do not know how to get the uploaded file (not the name) from this

  <input id="upload_content_id" type="file" name="upload_file" multiple>

and save the file in folder. I'm not quite sure how to read the file from handler which i have written:

@app.route('/uploadajax', methods = ['POST'])
def upldfile():
    if request.method == 'POST':
        file_val = request.files['file']

I will be grateful if anyone can help. Thank you in advance

Matthew Moisen
  • 14,590
  • 25
  • 104
  • 205
ox12
  • 17,618
  • 20
  • 63
  • 121
  • You can have a look at this post which suggests a flask-sijax to handle that http://stackoverflow.com/questions/14416706/upload-file-in-ajax-with-wtforms –  Aug 20 '13 at 12:21

2 Answers2

62

To answer your question...

HTML:

<form id="upload-file" method="post" enctype="multipart/form-data">
    <fieldset>
        <label for="file">Select a file</label>
        <input name="file" type="file">
    </fieldset>
    <fieldset>
        <button id="upload-file-btn" type="button">Upload</button>
    </fieldset>
</form>

JavaScript:

$(function() {
    $('#upload-file-btn').click(function() {
        var form_data = new FormData($('#upload-file')[0]);
        $.ajax({
            type: 'POST',
            url: '/uploadajax',
            data: form_data,
            contentType: false,
            cache: false,
            processData: false,
            success: function(data) {
                console.log('Success!');
            },
        });
    });
});

Now in your flask's endpoint view function, you can access the file's data via flask.request.files.

On a side note, forms are not tabular data, therefore they do not belong in a table. Instead, you should resort to an unordered list, or a definition list.

  • Can you explain the code: new FormData($('#upload-file')[0]); What does the "0" means? – nam Jan 12 '14 at 21:55
  • 2
    Use Firebug, or whichever developer tools you use to bring up you browser's console. Now, in your JavaScript file: console.log($("#upload-file")); - As you can see, it returns an object. Suffixing with "[0]" selects the first item in the object. FormData() creates a new FormData object, which is the object needed to send to your server. –  Mar 06 '14 at 19:44
  • I confirm that this should be the accepted answer. Works like charm! :) Thanks @onosendi! – swdev Mar 16 '14 at 22:29
  • 1
    As for your side note: unfortunatelly, given CSS current state (*), it is still an order of magnitude easier to have the input fields aligned one to another with a table than using other techniques. (*) It simply seens to be a missing use case on the CSS2 and 3 specs - -either that, or tables are indeed expected. – jsbueno Feb 27 '15 at 11:43
  • @onosendi tried to use your answer with some AJAX, do U know what I'm doing wrong here? http://stackoverflow.com/questions/36995516/getting-an-empty-immutablemultidict-object-from-jquery-request-data Thank you in advance! – mongotop May 06 '16 at 04:01
  • enctype="multipart/form-data" in the form is very important! – Dror Hilman Nov 28 '16 at 11:33
  • I get a deprecation warning when running this on Chrome: `XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/`. Changing `async` to `true` fixes it. – Gustavo Bezerra Oct 16 '17 at 08:00
  • @GustavoBezerra You can remove async:false in order to get rid of that error. See https://stackoverflow.com/questions/27736186/jquery-has-deprecated-synchronous-xmlhttprequest – zwep Apr 04 '18 at 10:39
  • Removed `async: false` from my answer. –  Aug 21 '18 at 04:55
5
    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)
蘇韋文
  • 81
  • 1
  • 6