将数据传递给 Axios 中的服务

ilv*_*sgm 3 javascript multipartform-data form-data react-native axios

我想_boundry在我的标题中设置。

首先,我发送表单数据:

//component.js

const form = new FormData();

form.append('email', 'eray@serviceUser.com')
form.append('password', '12121212')

dispatch(FetchLogin.action(form))
Run Code Online (Sandbox Code Playgroud)

其次,我准备api调用;

//loginService.js

import api from '@/Services'

export default async form => {
  const response = await api.post('user/login/', form)
  return response.data
}
Run Code Online (Sandbox Code Playgroud)

第三,我进行api调用;

//Services/index.js

import axios from 'axios'
import { Config } from '@/Config'

const instance =  axios.create({
  baseURL: Config.API_URL,
  headers: {
    'Content-Type': `multipart/form-data; boundary=${form._boundary}`, //Cannot access form here
  }, 
  timeout: 3000,
})

instance.interceptors.response.use(
  response => response,
  ({ message, response: { data, status } }) => {
    return handleError({ message, data, status })
  },
)

export default instance
Run Code Online (Sandbox Code Playgroud)

我想访问formto 中的数据axios instance以便能够form._boundryheaders.

我如何将form数据从传递loginService.jsServices/index.js

Phi*_*hil 7

当从浏览器执行 AJAX 请求时(通过fetchXMLHttpRequest),运行时知道如何处理某些请求正文格式,并会自动设置适当的Content-type标头

  • 如果请求正文是一个FormData实例,则将Content-type设置为multipart/form-data并且还将包含来自数据实例的适当的 mime 边界标记。

    multipart/form-data所有这些示例都将使用适当的mime 边界标记来发布数据

    const body = new FormData();
    
    // attach files and other fields
    body.append("file", fileInput.files[0]);
    body.append("foo", "foo");
    body.append("bar", "bar");
    
    // fetch
    fetch(url, { method: "POST", body });
    
    // XMLHttpRequest
    const xhr = new XMLHttpRequest();
    xhr.open("POST", url);
    xhr.send(body);
    
    // Axios
    axios.post(url, body);
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果请求正文是一个URLSearchParams实例,则将Content-type设置为application/x-www-form-urlencoded

    所有这些示例都将发布数据为application/x-www-form-urlencoded

    const body = new URLSearchParams({ foo: "foo", bar: "bar" });
    // serialises to "foo=foo&bar=bar"
    
    // fetch
    fetch(url, { method: "POST", body });
    
    // XMLHttpRequest
    const xhr = new XMLHttpRequest();
    xhr.open("POST", url);
    xhr.send(body);
    
    // Axios
    axios.post(url, body);
    
    Run Code Online (Sandbox Code Playgroud)

如果您打算以特定格式(例如、等content-type)发送字符串数据,则只需手动设置 ,因为运行时无法从数据推断类型。text/xmlapplication/json

const body = JSON.stringify({ foo: "foo", bar: "bar" });

// fetch
fetch(url, {
  method: "POST",
  headers: {
    "content-type": "application/json",
  },
  body
});

// XMLHttpRequest
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);
Run Code Online (Sandbox Code Playgroud)

在 Axios 上

Axios 会自动对传递到data参数中的 JavaScript 数据结构进行字符串化,并将Content-type标头设置为application/json,以便您在处理 JSON API 时只需要最少的配置

// no extra headers, no JSON.stringify()
axios.post(url, { foo: "foo", bar: "bar" })
Run Code Online (Sandbox Code Playgroud)

在幕后,Axios 使用XMLHttpRequest和 的规范,因此FormDataURLSearchParams适用。

axios v0.27.1 已损坏

此特定版本的 Axios 无法向 发出正确的请求FormData。不要使用它!

axios v1.0.0+ 已损坏

这接近于我自己的观点,但每一个 Axios 发布的 v1.0.0 版本都以某种方式从根本上被破坏了。我根本不建议任何人以任何理由使用它。

更好的替代方案是:

  • Fetch API(在 Node v18+ 中也可用)
  • 获取Node.js
  • ky用于浏览器

NodeJS

当从后端使用 Axios 时,它不会Content-typeFormData实例推断标头。您可以使用请求拦截器来解决此问题。

axios.interceptors.request.use(config => {
  if (config.data instanceof FormData) {
    Object.assign(config.headers, config.data.getHeaders());
  }
  return config;
}, null, { synchronous: true });
Run Code Online (Sandbox Code Playgroud)

或者在发出请求时简单地合并到标头中

axios.post(url, body, {
  headers: {
    "X-Any-Other-Headers": "value",
    ...body.getHeaders(),
  },
});
Run Code Online (Sandbox Code Playgroud)

请参阅https://github.com/axios/axios#form-data


关于 jQuery $.ajax()

jQuery 的$.ajax()方法(以及诸如 之类的便捷方法$.post())默认将请求正文有效负载发送为application/x-www-form-urlencoded. JavaScript 数据结构将使用jQuery.param()自动序列化,除非被告知不要这样做。如果希望浏览器Content-type根据body格式自动设置header,还需要在选项中进行配置

const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")

$.ajax({
  url,
  method: "POST",
  data: body,
  contentType: false, // let the browser figure it out
  processData: false  // don't attempt to serialise data
})
Run Code Online (Sandbox Code Playgroud)