2011-10-28 29 views
5

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

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> 

任何人有什么高见?

回答

1

你试过调整超时时间吗?对于2.5Mb,10秒可能已经足够,但不会更多。

+0

感谢Erick的提示 - 我在本地测试这个,所以10s对于大文件来说是足够的,但我会在现场环境中采取您的观点,并相应地提高超时时间。 – Journeyman

1

UPDATE

的一个spnet:MaxJsonDeserializerMembers元件必须被添加到你的的web.config文件的<appSettings>部,设置为其是Int32数据类型的最大值的等价物。

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

在官方documentation的这个页面,你就可以找到所有关于元素的信息以及它们的使用。

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

原帖由@Flxtr:Here

OLD

如果你想上传的文件,为什么不尝试使用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> 

另外,在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); 
} 

我知道这是不是最好的方式,但它工作,直到更好的东西走来。

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