jQuery .ajax post 因大型 JSON 对象而失败

标签 jquery ajax json post

我正在将 JSON 数据发布到 ASP.NET MVC2 服务器。我正在发布大型 JSON 字符串(其中包含从本地文件系统读取的 Base64 编码文件流)。 jQuery ajax 调用在文件大小约为 2.5Mb 时工作正常。一旦超过这个大小,ajax 调用就会失败(永远不会到达 Controller )。我无法准确检测出错误是什么 - 它似乎没有填充错误变量。

ajax调用如下:

$.ajax({
            type: "POST",
            dataType: 'json',
            timeout: 10000,
            url: "/Molecule/SaveMolecule",
            data: { jsonpost: postdata, moleculetype: _moleculeType, moleculefilestream: _moleculefilestream, changedproducts: stringifiedChangedProducts }, // NOTE the moleculeType being added here
            success: function (data) {
                if (data.rc == "success") {
                    $.log('ServerSuccess:' + data.message);

                    molecule_updateLocalInstance();

                    _bMoleculeIsDirty = false;
                    if (bReturnToMoleculeList != null && bReturnToMoleculeList == true) {
                        navigator_Go('/Molecule/Index/' + _moleculeType);
                    }
                    else {
                        _saveMoleculeButtonFader = setTimeout(function () {

                            $('#profilesave-container').delay(500).html('<img src="/content/images/tick.png" width="32px" height="32px" /><label>' + _moleculeSingularTerm + ' was saved</label>').fadeIn(500);

                            _saveMoleculeButtonFader = setTimeout(function () { $('#profilesave-container').fadeOut(1000); }, 2000);

                        }, 500);
                    }

                } else {
                    $.log('ServerUnhappy:' + data.message);
                    RemoveMoleculeExitDialog();
                }
            }
            , error: function (jqXHR, textStatus, errorThrown) {
                alert('Save failed, check console for error message:' +textStatus+' '+ errorThrown);
                MarkMoleculeAsDirty();
                $.log('Molecule Save Error:' + helper_objectToString(textStatus+' '+errorThrown));
            }
        });

其中 _moleculefilestream 是大型 Base64 编码流。

我的 web.config 包括以下内容:

<system.web.extensions>
    <scripting>
      <webServices>
        <jsonSerialization maxJsonLength="50000000">
        </jsonSerialization>
      </webServices>
    </scripting>
  </system.web.extensions>

有人有什么好主意吗?

最佳答案

更新

a spnet:MaxJsonDeserializerMembers元素必须添加到 <appSettings> web.config 文件的部分,设置为 2147483647,这相当于 Int32 的最大值数据类型。

<configuration>
  <appSettings>
    <add key="aspnet:MaxJsonDeserializerMembers" value="2147483647" />
  </appSettings>
</configuration>

在官方这个页面documentation ,您将能够找到有关元素及其用途的所有信息。

注意:在官方文档的部分中,建议不要调整为最大值,因为这存在安全风险。理想情况下,您应该检查要反序列化的项目数量,并尝试根据您使用的最大 json 大小进行估计。

@Flxtr 的原始帖子:Here

如果您想上传文件,为什么不尝试使用 FormData

例如:

function getDataForm() {

    var data = new FormData();

    var files = fileUploader.get(0).files;
    if (files.length > 0) {
        data.append("File", files[0]);
    }
    data.append("ImagePath", "");

    data.append("Id", ImageId);
    data.append("Name", txtName.val().trim());
    data.append("Description", txtDescription.val().trim());

    return data;
}

function save(data) {
    $.ajax({
        type: "POST",
        url: "/Files/SaveImage",
        contentType: false,
        processData: false,
        data: data,
        success: function (response) {

            if (response.success) {
                $.showMessage(messages.NAME, messages.SUCCESS, "success");
                closeForm();
                Files.ImageList.gridImages.ajax.reload();
            }
            else {
                $.showMessage(messages.NAME, response.message, "error");
            };

            btnSave.button('reset');
        },
        error: function (request, status, exception) {
            $.showMessage(messages.NAME, exception, "error");
            btnSave.button('reset');
        }
    });
};

然后,在服务器端,更改 Web 配置中的请求长度:

<httpRuntime targetFramework="4.6.1" maxRequestLength="65536"/>

例如:

<system.web>
    <compilation debug="true" targetFramework="4.6.1" />
    <httpRuntime targetFramework="4.6.1" maxRequestLength="65536"/>
    <customErrors mode="RemoteOnly">
        <error statusCode="401" redirect="/Error/401" />
        ...
        <error statusCode="411" redirect="/Error/411" />
    </customErrors>
  </system.web>

另外,更改参数 processDatafalse在ajax请求中:

$.ajax({
    url: "/Security/SavePermissions",
    type: "POST",
    processData: false,
    contentType: "application/json; charset=utf-8",
    data: JSON.stringify(pStrPermissions),
    success: function (response) {
        if (response.success) {
            panel.showAlert("Permisos", "Se han actualizado correctamente los permisos.", "success");
            resetForm();
        }
        else {
            $.showMessage("Permisos", response.message, "error");
        };
    },
    error: function (request, status, exception) {
        $.showMessage("Permisos", exception, "error");
    }
});

这些只是建议。唯一真正对我有用的是序列化列表并在服务器上反序列化它。

例如,在客户端:

function savePermissions(pLstObjPermissions) {
    $.ajax({
        url: "/Security/SavePermissions",
        type: "POST",
        dataType: "json",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify({ pStrPermissions: JSON.stringify(pLstObjPermissions)}) ,
        success: function (response) {
            if (response.success) {
                panel.showAlert("Permisos", "Se han actualizado correctamente los permisos.", "success");
                resetForm();
            }
            else {
                $.showMessage("Permisos", response.message, "error");
            };
        },
        error: function (request, status, exception) {
            $.showMessage("Permisos", exception, "error");
        }
    });
};

在服务器端:

public ActionResult SavePermissions(string pStrPermissions)
{
    var lLstObjResult = new Dictionary<string, object>();

    try
    {
        SecurityFactory.GetPermissionService().UpdateList(JsonConvert.DeserializeObject<IList<Permission>>(pStrPemissions));
        lLstObjResult.Add(MESSAGE, "Registro guardado exitosamente");
        lLstObjResult.Add(SUCCESS, true);
    }
    catch (Exception e)
    {
        lLstObjResult.Add(MESSAGE, e.Message);
        lLstObjResult.Add(SUCCESS, false);
    }

    return Json(lLstObjResult, JsonRequestBehavior.AllowGet);
}

我知道这不是最好的方法,但它会起作用,直到出现更好的方法。

如果您有更好的方法来解决此问题,请分享。

关于jQuery .ajax post 因大型 JSON 对象而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7931649/

相关文章:

php - ajax 调用后选中某些复选框

javascript - AJAX Date 无法正确显示日期

java - 无法显示Json数据

javascript - 当响应是 text/html 时,jQuery $.getJSON() 方法应该失败吗?

javascript - 将变量按字面意思放入 JSON 中

javascript - 悬停时鼠标移动动画

javascript - 在 KeyUp 和粘贴事件上限制 AJAX 请求

javascript - 从 jquery 模板问题开始

jquery - 为什么评级星星要换行?

javascript - 使用 get 方法在表单中创建随机 url