【问题标题】:jQuery .ajax post fails with large JSON objectjQuery .ajax 发布因大型 JSON 对象而失败
【发布时间】:2011-10-28 15:50:01
【问题描述】:

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

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>

有人有什么好主意吗?

【问题讨论】:

    标签: jquery ajax json post


    【解决方案1】:

    更新

    aspnet:MaxJsonDeserializerMembers 元素必须添加到 web.config 文件的 &lt;appSettings&gt; 部分,设置为 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 config 中更改请求长度:

    <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>
    

    另外,将ajax请求中的processData参数改为false

    $.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);
    }
    

    我知道这不是最好的方法,但它一直有效,直到出现更好的方法。

    如果你有更好的方法来解决这个问题,请分享。

    【讨论】:

      【解决方案2】:

      尝试设置 httpRuntime 的 maxRequestLength 属性。

      http://msdn.microsoft.com/en-us/library/e1f13641.aspx

      您可以通过位置标签将其设置为您需要的控制器/动作。

      【讨论】:

        【解决方案3】:

        您是否尝试过调整超时? 10 秒对于 2.5Mb 可能就足够了,但不会更多。

        【讨论】:

        • 感谢 Erick 的提示 - 我正在本地进行测试,因此 10 秒对于大文件来说已经足够了,但我认为你的观点是针对实时环境并会相应地提高超时时间。
        猜你喜欢
        • 1970-01-01
        • 2014-12-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多