POST 请求未将文件上传到服务器

时间:2021-06-19 06:50:42

标签: javascript node.js reactjs rest

我被这个问题困扰了 3 天。我在前端使用 React.js 和 axios 并想将文件上传到服务器。有一个 API 端点,它是一个像这样的后端点。

POST- https://88.66.123.122:20000/b1s/v1/Attachments2

此端点基本上将文件上传到服务器文件系统,成功响应状态为 201。当我使用桌面客户​​端 Postman 测试端点时,响应成功正常,此工具生成的代码片段是这样的。

Postman Snippet

但我想在浏览器 UI 中实现这件事。所以我为此使用 React.js。

此端点还需要在请求标头中使用授权 cookie,以确保用户已通过身份验证。因此,在 UI 中,我创建了一个登录按钮,该按钮基本上将带有硬编码凭据的 post 请求发送到 login 端点,并使用会话 ID 给我一个成功的响应。

我将会话 ID 保存在浏览器中作为上传文件的 cookie,但是当我随请求发送 cookie 时,我在浏览器中收到以下响应

Refused to set unsafe header "Cookie"

以及我使用以下 JSON 返回的响应。

POST https://88.66.123.122:20000/b1s/v1/Attachments2 [401 (Unauthorized)]

{
   "error" : {
      "code" : 301,
      "message" : {
         "lang" : "en-us",
         "value" : "Invalid session."
      }
   }
}

我不知道如何解决这个问题?您可以看到 GIF

代码:

import React from 'react';
import axios from 'axios';

const URL_LOGIN = `${process.env.REACT_APP_SERVER}Login`;
const COMPANY_DB = process.env.REACT_APP_DB;
const URL_ATTACHMENT = `${process.env.REACT_APP_SERVER}Attachments2`;
const CREDENTIALS = {
  UserName: process.env.REACT_APP_USERNAME,
  Password: process.env.REACT_APP_PASSWORD,
  CompanyDB: COMPANY_DB
};


function App() {
  const [isLogin, setIsLogin] = React.useState(false);
  const [selected, setSelected] = React.useState(null);

  function onClick() {
    setIsLogin(true);
    axios
      .post(URL_LOGIN, CREDENTIALS)
      .then(function (response) {
        setIsLogin(false);
        console.log(response.data);
      })
      .catch(function (err) {
        setIsLogin(false);
        console.log(err);
      });
  }

  // onUpload
  function handleUpload(event) {
    console.log('File set', event.target.files[0]);
    setSelected(event.target.files[0]);
  }

  function uploadSubmit() {
    const formData = new FormData();
    formData.append('files', selected, selected?.name);

    axios
      .post(URL_ATTACHMENT, formData)
      .then(function (response) {
        console.log('response', response);
      })
      .catch(function (err) {
        console.log('err', err);
      });
  }

  return (
    <div>
      <div>
        <button type="button" onClick={onClick} disabled={isLogin}>
          Login Create Cookie
        </button>
      </div>

      <hr />

      <div>
        <div>
          <input type="file" onChange={handleUpload} />
        </div>
        <button type="button" onClick={uploadSubmit}>
          Upload File
        </button>
      </div>
    </div>
  );
}

export default App;

3 个答案:

答案 0 :(得分:8)

cookies 由服务器管理,而不是客户端。在您的情况下,您使用的是带有 HttpOnly 标志的 cookie。客户端脚本不允许您读取 Cookie 的值,因为它是一种安全威胁。

在您的 nodejs 应用程序中,服务器必须发送 Cookie 作为响应。服务器必须做这样的事情:

// nodejs (express)
res.cookie('cookieKey', "value", { maxAge: 900000, httpOnly: true });

注意 httpOnly 标志,该标志可防止客户端脚本使用 cookie。

一旦您设置 cookie 以响应您的 NodeJs (Express) 请求,您的浏览器应自动开始随您的每个请求发送 Cookie。

答案 1 :(得分:0)

如果请求是跨域的,请务必在 axios 请求中添加 withCredentials: true 作为 header

答案 2 :(得分:0)

从服务器成功获取cookie/token后,在header中传递token。 (取决于您如何保护 API 端点。)

axios
      .post(URL_ATTACHMENT, formData, { headers : { header : token }})
      .then(function (response) {
        console.log('response', response);
      })
      .catch(function (err) {
        console.log('err', err);
      });