Home > Net >  post xlsx file to flask route with React async/await
post xlsx file to flask route with React async/await

Time:07-08

I have a project where I was originally using fetch for all of my requests, and my excel upload function was working fine. I recently made a lot of changes to my application because I added user login and authentication, so I am now trying to reconfigure my routes using async await in React. I am getting different errors that I don't know how to solve. Sometimes when I try to submit the uploaded file I get a 400 error for a bad request, usually saying ""The browser (or proxy) sent a request that this server could not understand.\nKeyError: 'project'". Or I am getting an error on the back-end that says "ValueError: Excel file format cannot be determined, you must specify an engine manually."

I am really confused about where the error is actually occurring because it seems to be reaching the Flask route and then failing.

This is my current request on the front-end:

  const onSubmit = async (ev) => {
    ev.preventDefault();
    let formData = new FormData();
    formData.append("project", selectedFile);
    // let status = 0;
    const data = await api.post("/projects", {
      body: formData,
    });
    if (!data.ok) {
      console.log(data);
      console.log("error");
    } else {
      console.log(data);
      console.log("uploaded");
    }
  };

and the back-end route:

@projects.route('/projects', methods=['POST'])
@authenticate(token_auth)
def request_load_pickle_sim():
    fn = save_file(None, "project", "xlsx")
    print(fn)
    request.files["project"].save(fn)
    result = process_raw_util_xl_file(fn)
    claims = result['claims']
    print(claims)
    utilities = result['utilities']
    weights = result['weights']
    maxdiff_scores = result['maxdiff_scores']
    data = jsonify(claims)
    print(data)
    mdp = MaxDiffProject()
    mdp.config = MutableDict({
        'claims': claims,
        'utilities': utilities,
        'weights': weights,
        'maxdiff_scores': maxdiff_scores
    })
    print(mdp.config)
    db.session.add(mdp)
    db.session.commit()
    mdp = MaxDiffProject().query.first()
    project_config = mdp.config
    claims = project_config['claims']
    print(claims)
    data = jsonify(claims)
    return data

My debugger is printing the instance of the file, so it seems like the backend is receiving the file? But after that nothing is working. The file is passed to the process_raw_util_xl_file function (which is where the ValueError error is coming from). I can't figure out what the core issue is because I'm getting conflicting errors. I guess I'm just confused because it was all working fine when I had fetch requests.

The function on the backend is breaking here:

def process_raw_util_xl_file(xl_fn):
    # df = pd.read_csv(xl_fn.read())
    df = pd.read_excel(xl_fn)  # read the excel file
    print(df)
    row = df.shape[0]  # df.shape[0] = Number of rows, df.shape[1] = number of columns
    index_col = [col for col in df if 'id' in col.lower()][0]
    print(index_col)
    df.set_index(index_col, inplace=True)  # Setting the ID as the index
    # weights = df['Weights'] if 'Weights' in df else pd.Series([1]*row)         # Creating the weights array if there are weights , otherwise an array of 1's with # of rows

    if 'Weights' not in df:
        df['Weights'] = 1

    weights = df['Weights']
    df.drop('Weights', axis=1, inplace=True)
    sum = weights.values.sum()  # Sum of the weights

    # if 'Weights' in df: df = df.drop('Weights', axis=1)                        # removing weights from df if they are there
    rlh_cols = [col for col in df if 'rlh' in col.lower()][:1]
    df = df.drop(rlh_cols, axis=1)  # removing RLH from df if they are there

    max_diff_scores = (e ** df) / (1   e ** df) * 100  # exp the values of the dataframe with

    utils = df

    return {
        "utilities": utils,
        "claims": [col for col in utils],
        "maxdiff_scores": max_diff_scores,
        "weights": weights
    }

CodePudding user response:

You are posting an object as a body paramter to the server which has a content type as application/json whereas according the HTTP protocol, to post form-data the content type must be multipart/form-data. Here's how you are doing it,

let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", {
  body: formData,
});

According to the docs (at page end) you must post form data like this,

let formData = new FormData();
formData.append("project", selectedFile);
// let status = 0;
const data = await api.post("/projects", formData);

Also you cannot post body and form data at a same time within single request.

  • Related