You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用jQuery $.post发送FormData报Illegal Invocation错误原因分析

问题

使用jQuery的简写$.post方法发送包含文件上传的FormData进行AJAX请求时,遇到了“Illegal Invocation”错误,但使用完整的$.ajax方法时该错误消失。后端采用CodeIgniter框架。

表单代码

<form id="add_category_form" action="<?= base_url("CategoriesController/process_add_category") ?>" method="post" enctype="multipart/form-data">
    <input type="hidden" name="<?= $this->security->get_csrf_token_name() ?>" value="<?= $this->security->get_csrf_hash() ?>" />
    <h2>Add a Category</h2>
    <ul>
        <li>
            <input type="text" name="name" required>
            <label>Category Name</label>
        </li>
        <li>
            <textarea name="description" required></textarea>
            <label>Description</label>
        </li>
        <label>Upload Images (5 Max)</label>
        <input type="file" name="image" id="category_image" accept="image/*">
    </ul>
    <!-- FIXME: center the content of this last li tag -->
    <button type="button" data-dismiss="modal" aria-label="Close">Cancel</button>
    <button type="submit">Save</button>
</form>

使用$.post的代码

$(document).ready(function() {
  $("#add_category_form").submit(function(e) {
    e.preventDefault();
    let url = $(this).attr("action");

    if ($("#category_image").val() == "") {
      alert("Please add an image");
    } else {
      let formData = new FormData(this); // Pass the form element

      $.post(url, formData, function(response) {
        console.log(response);
        csrfName = response.csrfName;
        $("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
      }, "json");
    }
    return false;
});

使用$.ajax的代码

$(document).ready(function() {
  $("#add_category_form").submit(function(e) {
    e.preventDefault();
    if ($("#category_image").val() == "") {
      alert("Please add an image");
    }

    let formData = new FormData(this);
    $.ajax({
      url: "<?= base_url(''); ?>CategoriesController/process_add_category",
      type: "POST",
      data: formData,
      processData: false,
      contentType: false,
      dataType: "json",
      success: function(response) {
        console.log(response);
        csrfName = response.csrfName;
        $("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
      },
      error: function(xhr, status, error) {
        console.error("AJAX Error:", status, error);
      }
    });

    return false;
  });
});

原因分析与解答

为啥$.post会报“Illegal Invocation”错误?

$.post是$.ajax的简化版,它默认做了两个不适合文件上传的操作:

  • 自动把请求头的contentType设为application/x-www-form-urlencoded,这是普通文本表单的格式,不支持二进制文件传输。
  • 自动开启processData: true,会把传入的数据转成URL编码的字符串。但FormData是专门存储文件的二进制容器,jQuery强行序列化它时,会触发浏览器安全限制,抛出“Illegal Invocation”错误。

为啥$.ajax能正常运行?

你在$.ajax的配置里手动设置了两个关键参数:

  • processData: false:告诉jQuery不要对FormData进行序列化处理,直接传递原始对象。
  • contentType: false:让浏览器自动生成适合FormData的请求头(multipart/form-data,这才是文件上传的正确格式)。

这两个参数是文件上传AJAX请求的必备配置,但$.post这类简写方法没有提供直接设置的入口,无法满足FormData的传输要求。

非要用$.post行不行?

可以,但需要改成带配置对象的写法,本质和$.ajax无差异:

$.post({
  url: url,
  data: formData,
  processData: false,
  contentType: false,
  dataType: "json",
  success: function(response) {
    console.log(response);
    csrfName = response.csrfName;
    $("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
  }
});

不过这种写法反而不如直接用$.ajax清晰,更推荐使用完整的$.ajax配置。

内容的提问来源于stack exchange,提问作者Adrian Gaile Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:43:13