1

I'm trying to upload and image using Bootstrap-Vue Form File Input and send it to Flask Backend via POST using Axios library, then store in a folder.

My problem is that Flask can't find "file" in "request.files". Pretty sure I'm falling in a rookie mistake.

That's my code:

Frontend:

<template>
  <div class="mx-5 container-fluid">
    <div class="mx-5 row">
      <div class="col-sm-10">
                <b-form-file
                  type="file"
                  id="file"
                  v-model="file"
                  :state="Boolean(file)"
                  ref="file"
                  placeholder="Choose a file or drop it here..."
                  drop-placeholder="Drop file here..."
                  v-on:change="submitFile"
                ></b-form-file>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      file: null,
    };
  },
  methods: {
    submitFile() {
      /* Initialize the form data */
      const path = 'http://localhost:5000/single-file';
      const formData = new FormData();
      /* Add the form data we need to submit */
      formData.append('file', this.file);
      /* Make the request to the POST /single-file URL */
      axios.post(path,
        formData,
        {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        }).then(() => {
        // console.log('SUCCESS!!');
      })
        .catch(() => {
          // console.log('FAILURE!!');
        });
    },
  },
};

Backend:

from flask import Flask, jsonify, request, send_file, redirect, url_for
from werkzeug.utils import secure_filename
import os

# configuration
DEBUG = True
UPLOAD_FOLDER = '/images'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

@app.route('/single-file', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            print('No file part')
            return redirect(request.url)
        file = request.files['file']
        # If the user does not select a file, the browser submits an
        # empty file without a filename.
        if file.filename == '':
            print('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return redirect(url_for('download_file', name=filename))
    return ''

if __name__ == '__main__':
    app.run()

I get HTTP code 302 (redirect) and print in console 'No file part'.

Any help would be very apreciated.

murcian0
  • 11
  • 2

2 Answers2

0

I can't see an obvious mistake in your code, it seems that the request is correctly passed through from your frontend and backend.

What I would suggest is to use Postman to decouple your frontend and backend in this case. If you get a correct response when using Postman, you can narrow down that the error is in the frontend, the browser, or something about axios which is meddling with the request data.

Also, try to get an error message, or print why flask thinks "file" isnt in request.files, it should be there if everything works as intended

c8999c 3f964f64
  • 1,430
  • 1
  • 12
  • 25
0

I followed the response for Get the data received in a Flask request to get to the flask documentation for the Request class: Each key in files is the name from the <input type="file" name="">, which means that most likely you have to change 'file' from file = request.files['file'] to point to the actual filename that was selected from the file selection menu.

branco
  • 142
  • 9