Skip to content
Advertisement

How to send file from React/Next.js client UI to Node server and next to Flask service

I want to send an Excel file from UI to Node JS, extract authorization token in NODЕ JS and then send to the Flask Server.

I don’t want to share my authorization token with the client UI, so I don’t want to send the file from there directly to Flask API. Also, I would like not to save the file on Node server-side, like if I send the file with FormData and parse it with formidable on Node server-side.

Something like: Reakt UI => Node.js(attach authorization token) => Flask(server)

My idea is to convert the file to array buffer, send it to Node server, and from there send it with the authorization token to Flask service.

My best approach to the moment is: In my client, I take the file with an input tag, create a buffer, and make a post request to API.

const changeHandler = (event) => {
  const file = readFile(event.target.files[0]);
  event.target.value = null;
}

function readFile(file) {
  new Response(file).arrayBuffer().then(function(buffer) {
    handleSubmission(buffer)
  });
}

function handleSubmission(file) {
  // var blob = new Blob([file], {type: 'application/vnd.openxmlformats- officedocument.spreadsheetml.sheet'})

  fetch(
    '/api/admin/uploadGuestTable',
    {
      method: 'POST',
      body: file
    }
  )
  .then((response) => response.json())
  .then((result) => {
    console.log('Success:', result);
  })
  .catch((error) => {
    console.error('Error:', error);
  });
};

From API endpoint I make post request to Flask:

import auth0 from "../../../assets/utils/auth0";
const fetch = require('node-fetch');

export default auth0.requireAuthentication(async function uploadTable(req, res) {

    const body = await req.body;

    var url;
    if (process.env.DOCKER_ENV === 'development') {
        url = `http://app:5000/admin/upload/table`;
    } else {
        url = `${process.env.NEXT_PUBLIC_API_BASE}/admin/upload/table`;
    }

    const response = await fetch(url, {
        method: "POST",
        body: body
    });

    res.status(200).json(JSON.stringify("Success"));
});

In Flask I receive the binries and want to create pandas dataframe:

@bp.route('upload/table', methods=['POST'])
# @requires_auth
def upload_guests_table():
    data = request.data
    df = pd.read_excel(data, engine='openpyxl')
    return jsonify("Success"), 200

I receive this traceback:

Traceback (most recent call last):
File "D:projectsbnbvenvlibsite-packagesflaskapp.py", line 2447, in wsgi_app
  response = self.full_dispatch_request()
File "D:projectsbnbvenvlibsite-packagesflaskapp.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "D:projectsbnbvenvlibsite-packagesflask_corsextension.py", line 161, in wrapped_function
  return cors_after_request(app.make_response(f(*args, **kwargs)))
File "D:projectsbnbvenvlibsite-packagesflaskapp.py", line 1821, in handle_user_exception
  reraise(exc_type, exc_value, tb)
File "D:projectsbnbvenvlibsite-packagesflask_compat.py", line 39, in reraise
  raise value
File "D:projectsbnbvenvlibsite-packagesflaskapp.py", line 1950, in full_dispatch_request
  rv = self.dispatch_request()
File "D:projectsbnbvenvlibsite-packagesflaskapp.py", line 1936, in dispatch_request
  return self.view_functions[rule.endpoint](**req.view_args)
File "D:projectsbnbrental_appback_endappadmin.py", line 65, in upload_guests_table
  df = pd.read_excel(data, engine='openpyxl')
File "D:projectsbnbvenvlibsite-packagespandasutil_decorators.py", line 296, in wrapper
  return func(*args, **kwargs)
File "D:projectsbnbvenvlibsite-packagespandasioexcel_base.py", line 304, in read_excel
  io = ExcelFile(io, engine=engine)
File "D:projectsbnbvenvlibsite-packagespandasioexcel_base.py", line 867, in __init__
  self._reader = self._engines[engine](self._io)
File "D:projectsbnbvenvlibsite-packagespandasioexcel_openpyxl.py", line 480, in __init__
  super().__init__(filepath_or_buffer)
File "D:projectsbnbvenvlibsite-packagespandasioexcel_base.py", line 355, in __init__
  self.book = self.load_workbook(BytesIO(filepath_or_buffer))
File "D:projectsbnbvenvlibsite-packagespandasioexcel_openpyxl.py", line 492, in load_workbook
  filepath_or_buffer, read_only=True, data_only=True, keep_links=False
File "D:projectsbnbvenvlibsite-packagesopenpyxlreaderexcel.py", line 316, in load_workbook
  data_only, keep_links)
File "D:projectsbnbvenvlibsite-packagesopenpyxlreaderexcel.py", line 124, in __init__
  self.archive = _validate_archive(fn)
File "D:projectsbnbvenvlibsite-packagesopenpyxlreaderexcel.py", line 96, in _validate_archive
  archive = ZipFile(filename, 'r')
File "C:UsersMitkoAppDataLocalProgramsPythonPython37libzipfile.py", line 1258, in __init__
  self._RealGetContents()
File "C:UsersMitkoAppDataLocalProgramsPythonPython37libzipfile.py", line 1343, in _RealGetContents
  fp.seek(self.start_dir, 0)
ValueError: negative seek value -45960242

I am missing something essential or my approach isn’t correct. Will appreciate any help or guidance. Thanks!

Advertisement

Answer

May be this answer will help? Though it uses Form-Data lib.

Edit

Here example code for express and flask

// index.js
const uploadStream = (file) => {
  pass = PassThrough()
  const form = new FormData();
  form.append('flask_file_field', pass, file.originalFilename);
  form.submit('http://localhost:5000/upload', (err, res) => {
    console.error(err);
    res.resume();
  });
  return pass
};

app.post('/upload', async (req, res) => {
    const form =  formidable({
      fileWriteStreamHandler: uploadStream
    });
    form.parse(req, (err, fields, files) => {
      res.json('Success!');
    });
});

and

# server.py
@app.route('/upload', methods=['POST'])
def upload_file():
    if 'flask_file_field' not in request.files:
        flash('No file part')
        return redirect(request.url)
    file = request.files['flask_file_field']
    if file.filename == '':
        flash('No selected file')
        return redirect(request.url)
    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(UPLOAD_FOLDER, filename))
        return f'Uploaded {file.filename}'
    return 'File is not allowed!'

working code here

Edit2

problem in your code is in express part. You are expecting to receive files from body, but files are not there

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement