2011-10-28 20 views
5

Publikuję dane JSON na serwerze ASP.NET MVC2. Publikuję duże ciągi JSON (które zawierają strumień pliku zakodowany w base64, odczytany z lokalnego systemu plików). Wywołanie ajax jQuery działa dobrze do wielkości plików około 2,5 MB. Po przekroczeniu tego rozmiaru wywołanie ajaxa nie działa (nigdy nie dostaje się do kontrolera). Nie mogę dokładnie wykryć błędu - wydaje się, że nie wypełnia on zmiennych błędów.jQuery .ajax post kończy się niepowodzeniem z dużym obiektem JSON

AJAX połączenia jest następujący:

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

gdzie _moleculefilestream jest duży strumień base64 kodowane.

Moje web.config zawiera następujące elementy:

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

Ktoś ma jakieś dobre pomysły?

Odpowiedz

1

Czy próbowałeś dostosować limit czasu? 10 sekund może wystarczyć na 2,5Mb, ale nie więcej.

+0

Dzięki za wskazówkę Erick - testuję to lokalnie, więc 10 jest wystarczające dla dużych plików, ale przyjmuję twój punkt widzenia dla środowiska na żywo i odpowiednio podniosę czas oczekiwania. – Journeyman

1

UPDATE

element spnet:MaxJsonDeserializerMembers należy dodać do sekcji <appSettings> swojego pliku web.config, ustawienie który jest odpowiednikiem wartości maksymalnej typu Int32 danych.

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

Na tej stronie oficjalnej documentation, będzie można znaleźć wszystkie informacje na temat elementów, jak i ich stosowanie.

Uwaga: W części oficjalnej dokumentacji zaleca się nie dostosowywać do wartości maksymalnej, ponieważ stanowi ona zagrożenie dla bezpieczeństwa. Najlepiej sprawdzić liczbę elementów, które chcesz deserializować, i spróbować oszacować na podstawie maksymalnego rozmiaru json, którego używasz.

Original post przez @Flxtr: Here

OLD

Jeśli chcesz przesłać plik, to dlaczego nie spróbować użyć FormData

Na przykład:

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'); 
     } 
    }); 
}; 

Następnie , po stronie serwera, zmień długość żądania w konfiguracji sieci:

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

Na przykład:

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

także zmienić parametr processData do false we wniosku 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"); 
    } 
}); 

Są to tylko sugestie. Jedyną rzeczą, która faktycznie działała dla mnie była serializacja listy i deserializacja jej na serwerze.

Na przykład, po stronie klienta:

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"); 
     } 
    }); 
}; 

Po stronie serwera:

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

wiem, że nie jest to najlepszy sposób, ale działa aż coś lepszego przyjdzie.

Jeśli masz lepszy sposób na rozwiązanie tego problemu, udostępnij go.

Powiązane problemy