如何将文件从 React/Next.js 客户端 UI 发送到 Node 服务器以及 Flask 服务旁边

Dim*_*zov 5 python flask pandas reactjs next.js

我想从 UI 发送一个 Excel 文件到 Node JS,在 NOD\xd0\x95 JS 中提取授权令牌,然后发送到 Flask 服务器。

\n

我不想与客户端 UI 共享我的授权令牌,因此我不想将文件从那里直接发送到 Flask API。另外,我不想将文件保存在 Node 服务器端,就像我用 FormData 发送文件并在 Node 服务器端用强大的解析它一样。

\n

类似于:Reakt UI => Node.js(附加授权令牌)=> Flask(服务器)

\n

我的想法是将文件转换为数组缓冲区,将其发送到 Node 服务器,然后从那里将其与授权令牌一起发送到 Flask 服务。

\n

目前我最好的方法是:\n在我的客户端中,我获取带有输入标记的文件,创建一个缓冲区,并向 API 发出发布请求。

\n
const changeHandler = (event) => {\n  const file = readFile(event.target.files[0]);\n  event.target.value = null;\n}\n\nfunction readFile(file) {\n  new Response(file).arrayBuffer().then(function(buffer) {\n    handleSubmission(buffer)\n  });\n}\n\nfunction handleSubmission(file) {\n  // var blob = new Blob([file], {type: 'application/vnd.openxmlformats- officedocument.spreadsheetml.sheet'})\n\n  fetch(\n    '/api/admin/uploadGuestTable',\n    {\n      method: 'POST',\n      body: file\n    }\n  )\n  .then((response) => response.json())\n  .then((result) => {\n    console.log('Success:', result);\n  })\n  .catch((error) => {\n    console.error('Error:', error);\n  });\n};\n
Run Code Online (Sandbox Code Playgroud)\n

我从 API 端点向 Flask 发出发布请求:

\n
import auth0 from "../../../assets/utils/auth0";\nconst fetch = require('node-fetch');\n\nexport default auth0.requireAuthentication(async function uploadTable(req, res) {\n\n    const body = await req.body;\n\n    var url;\n    if (process.env.DOCKER_ENV === 'development') {\n        url = `http://app:5000/admin/upload/table`;\n    } else {\n        url = `${process.env.NEXT_PUBLIC_API_BASE}/admin/upload/table`;\n    }\n\n    const response = await fetch(url, {\n        method: "POST",\n        body: body\n    });\n\n    res.status(200).json(JSON.stringify("Success"));\n});\n
Run Code Online (Sandbox Code Playgroud)\n

在 Flask 中,我收到二进制文件并想要创建 pandas 数据框:

\n
@bp.route('upload/table', methods=['POST'])\n# @requires_auth\ndef upload_guests_table():\n    data = request.data\n    df = pd.read_excel(data, engine='openpyxl')\n    return jsonify("Success"), 200\n
Run Code Online (Sandbox Code Playgroud)\n

我收到这个回溯:

\n
Traceback (most recent call last):\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\app.py", line 2447, in wsgi_app\n  response = self.full_dispatch_request()\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\app.py", line 1952, in full_dispatch_request\nrv = self.handle_user_exception(e)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask_cors\\extension.py", line 161, in wrapped_function\n  return cors_after_request(app.make_response(f(*args, **kwargs)))\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\app.py", line 1821, in handle_user_exception\n  reraise(exc_type, exc_value, tb)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\_compat.py", line 39, in reraise\n  raise value\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\app.py", line 1950, in full_dispatch_request\n  rv = self.dispatch_request()\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\flask\\app.py", line 1936, in dispatch_request\n  return self.view_functions[rule.endpoint](**req.view_args)\nFile "D:\\projects\\bnb\\rental_app\\back_end\\app\\admin.py", line 65, in upload_guests_table\n  df = pd.read_excel(data, engine='openpyxl')\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\util\\_decorators.py", line 296, in wrapper\n  return func(*args, **kwargs)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py", line 304, in read_excel\n  io = ExcelFile(io, engine=engine)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py", line 867, in __init__\n  self._reader = self._engines[engine](self._io)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\io\\excel\\_openpyxl.py", line 480, in __init__\n  super().__init__(filepath_or_buffer)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\io\\excel\\_base.py", line 355, in __init__\n  self.book = self.load_workbook(BytesIO(filepath_or_buffer))\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\pandas\\io\\excel\\_openpyxl.py", line 492, in load_workbook\n  filepath_or_buffer, read_only=True, data_only=True, keep_links=False\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\openpyxl\\reader\\excel.py", line 316, in load_workbook\n  data_only, keep_links)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\openpyxl\\reader\\excel.py", line 124, in __init__\n  self.archive = _validate_archive(fn)\nFile "D:\\projects\\bnb\\venv\\lib\\site-packages\\openpyxl\\reader\\excel.py", line 96, in _validate_archive\n  archive = ZipFile(filename, 'r')\nFile "C:\\Users\\Mitko\\AppData\\Local\\Programs\\Python\\Python37\\lib\\zipfile.py", line 1258, in __init__\n  self._RealGetContents()\nFile "C:\\Users\\Mitko\\AppData\\Local\\Programs\\Python\\Python37\\lib\\zipfile.py", line 1343, in _RealGetContents\n  fp.seek(self.start_dir, 0)\nValueError: negative seek value -45960242\n
Run Code Online (Sandbox Code Playgroud)\n

我遗漏了一些重要的内容或者我的方法不正确。\n非常感谢任何帮助或指导。\n谢谢!

\n

小智 4

也许这个答案会有帮助?虽然它使用Form-Data库。

编辑

express这里是和 的示例代码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!');
    });
});
Run Code Online (Sandbox Code Playgroud)

# 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!'
Run Code Online (Sandbox Code Playgroud)

工作代码在这里

编辑2

您的代码中存在express部分问题。您期望从 body 接收文件,但文件不存在