4

Below are the snippets of my code regarding file upload.

Here is my HTML code where I will choose and upload the file:

<form ng-click="addImportFile()" enctype="multipart/form-data">
    <label for="importfile">Import Time Events File:</label><br><br>
    <label for="select_import_file">SELECT FILE:</label><br>
    <input id="import_file" type="file" class="file btn btn-default" ng-disabled="CutOffListTemp.id== Null" data-show-preview="false">
    <input class="btn btn-primary" type="submit" name="submit" value="Upload" ng-disabled="CutOffListTemp.id== Null"/><br/><br/>
</form>

This is my controller that will link both html and my python file:

angular.module('hrisWebappApp').controller('ImportPayrollCtrl', function ($scope, $state, $stateParams, $http, ngTableParams, $modal, $filter) {
  $scope.addImportFile = function() {
    $http.post('http://127.0.0.1:5000/api/v1.0/upload_file/' + $scope.CutOffListTemp.id, {})
    .success(function(data, status, headers, config) {
      console.log(data);

      if (data.success) {
        console.log('import success!');
      } else {
        console.log('importing of file failed' );
      }
    })
    .error(function(data, status, headers, config) {});
};

This is my python file:

@api.route('/upload_file/<int:id>', methods=['GET','POST'])
@cross_origin(headers=['Content-Type'])
def upload_file(id):
    print "hello"
    try:
        os.stat('UPLOAD_FOLDER')
    except:
        os.mkdir('UPLOAD_FOLDER')
    file = request.files['file']
    print 'filename: ' + file.filename

    if file and allowed_file(file.filename):
        print 'allowing file'
        filename = secure_filename(file.filename)
        path=(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
        file.save(path) #The end of the line which save the file you uploaded.
        return redirect(url_for('uploaded_file',
                                            filename=filename))
    return '''
        <!doctype html>
        <title>Upload new File</title>
        <h1>Upload new File</h1>
        <p>opsss it seems you uploaded an invalid filename please use .csv only</p>

        <form action="" method=post enctype=multipart/form-data>
          <p><input type=file name=file>
             <input type=submit value=Upload>
        </form>
        '''

And the result in the console gave me this even if I select the correct format of file:

<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<p>opsss it seems you uploaded an invalid filename please use .csv only</p>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>

This is not returning to my HTML and I cannot upload the file.

thinkmind
  • 115
  • 2
  • 16

2 Answers2

3

Hi I can finally upload the file, I change the angular part, I change it by this:

    $scope.addImportFile = function() {
     var f = document.getElementById('file').files[0]; console.log(f);
     var formData = new FormData();
     formData.append('file', f);
                        $http({method: 'POST', url: 'http://127.0.0.1:5000/api/v1.0/upload_file/' +$scope.CutOffListTemp.id,
                         data: formData,
                         headers: {'Content-Type': undefined},
                         transformRequest: angular.identity})
                        .success(function(data, status, headers, config) {console.log(data);
                        if (data.success) {
                            console.log('import success!');

                        }
                    })
                    .error(function(data, status, headers, config) {
                    });
            // }
        };
thinkmind
  • 115
  • 2
  • 16
1

The first thing is about the post request. Without ng-click="addImportFile()", the browser will usually take care of serializing form data and sending it to the server. So if you try:

<form method="put" enctype="multipart/form-data" action="http://127.0.0.1:5000/api/v1.0/upload_file">
    <label for="importfile">Import Time Events File:</label><br><br>
    <label for="select_import_file">SELECT FILE:</label><br>
    <input id="import_file" type="file" name="file" class="file btn btn-default" ng-disabled="CutOffListTemp.id== Null" data-show-preview="false">
    <input class="btn btn-primary" type="submit" name="submit" value="Upload" ng-disabled="CutOffListTemp.id== Null"/><br/><br/>
</form>

and then in python, make your request url independent of scope.CutOffListTemp.id: @api.route('/upload_file', methods=['GET','POST'])

It probably will work.

Alternatively, if you want to use your custom function to send post request, the browser will not take care of the serialization stuff any more, you will need to do it yourself.

In angular, the API for $http.post is: $http.post('/someUrl', data).success(successCallback); If we use "{}" for the data parameter, which means empty, the server will not find the data named "file" (file = request.files['file']). Thus you will see Bad Request

To fix it, we need to use formData to make file upload which requires your browser supports HTML5:

$scope.addImportFile = function() {
    var f = document.getElementById('file').files[0]
    var fd = new FormData();
    fd.append("file", f);

    $http.post('http://127.0.0.1:5000/api/v1.0/upload_file/'+$scope.CutOffListTemp.id,
               fd,
               headers: {'Content-Type': undefined})
    .success......

Other than using the native javascript code above, there are plenty great angular file upload libraries which can make file upload much easier for angular, you may probably want to have a look at one of them (reference: File Upload using AngularJS):

Community
  • 1
  • 1
Xin Zeng
  • 23
  • 1
  • 6
  • I tried this one but still getting an error. Upon analyzing it, the file itself was not saving upon requesting the server. Is the error on AngularJs or HTMLL? Thanks. – thinkmind Aug 30 '14 at 01:08