POST请求未向服务器上传文件

14

我被这个问题困扰了3天。 我在前端使用React.js和axios,想将文件上传到服务器。存在一个API端点,它是一个post端点,类似于这样。

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;

1
当您从浏览器发送Cookie时,它会在Cookie中添加HttpOnly标志。HttpOnly cookie标志是浏览器中的安全功能,用于防止通过客户端脚本显示Cookie。应该由服务器设置Cookie,并且浏览器在每个请求中内部管理发送Cookie。因此,您不需要显式设置Cookie头。 - Amir Saleem
你在什么时候遇到了“拒绝设置不安全的标头‘Cookie’”错误?是在调用uploadSubmit()函数时吗? - Tasos K.
@TasosK。当我在uploadSubmit() axios头配置中设置cookie时。 - Ven Nilson
@VenNilson 我会期望cookies自动发送。如果您删除此配置,它会如何行为?另外,您能分享一下这段代码部分(axios头部配置)吗? - Tasos K.
3个回答

9

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

在您的nodejs应用程序中,服务器必须在响应中发送一个Cookie。服务器必须执行类似以下操作:

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

注意httpOnly标志,该标志可以防止客户端脚本使用cookie。
一旦你在Node.js(Express)请求的响应中设置了cookie,你的浏览器应该自动开始发送Cookie。

谢谢你的回答。所以我需要创建一个node.js脚本来完成这个任务。你能否提供一个node.js/express的代码片段或分享一下?我在Node.js方面完全是个新手。 - Ven Nilson
是的,从您的axios请求中删除Cookie头,它应该可以工作。浏览器将在幕后自动设置每个请求的Cookie。 - Amir Saleem
你的意思是端点应该是 /b1s 而不是 https://88.66.123.122:20000/b1s/v1/Attachments2。我已经更新了我的问题中的代码并删除了 cookie 逻辑。 - Ven Nilson
让我们在聊天中继续这个讨论 - Ven Nilson
请查看GIF(https://s6.gifyu.com/images/sample.gif)。 - Ven Nilson
显示剩余6条评论

0

在成功从服务器获取cookie/token后,将token传递到header中。(根据您如何保护API端点而定。)

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

0
如果请求是跨源的,请确保在axios请求中添加withCredentials: true作为一个头。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接