example - webrequest post parameters c#
La solicitud no espera respuesta en.net (7)
¿Ha comprobado el límite de tamaño del archivo IIS en el servidor remoto? Su valor predeterminado es 30 MB, por lo que si los archivos que intentas subir son más grandes, fallará. a continuación se explica cómo cambiar el límite de carga (IIS7): http://www.web-site-scripts.com/knowledge-base/article/AA-00696/0/Increasing-maximum-allowed-size-for-uploads-on -IIS7.html
Tengo un servicio de Windows que está cargando archivos al otro sitio web que los está procesando. El problema es que con archivos pequeños funciona bien y recibe una respuesta desde allí, pero con archivos grandes (aproximadamente 6 minutos para procesar) deja para siempre en modo de espera.
Aquí está la parte del código del método de publicación del sitio web externo:
try
{
...
LogResults();
return string.Empty;
}
catch (Exception e)
{
return e.Message;
}
El problema es que puedo ver registros incluso para archivos grandes, por lo que el sitio web siempre devuelve valor, pero para archivos grandes mi servicio de Windows no los espera.
Y aquí está el código del servicio de Windows
var valuesp = new NameValueCollection
{
{ "AccountId", datafeed.AccountId }
};
byte[] resultp = UploadHelper.UploadFiles(url, uploadFiles, valuesp);
response = Encoding.Default.GetString(resultp);
UploadFiles
método UploadFiles
devuelve valor para archivos pequeños, pero esperando por siempre los grandes.
Aquí está el código completo de UploadFiles
public static byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
{
var request = WebRequest.Create(address);
request.Timeout = System.Threading.Timeout.Infinite; //3600000; // 60 minutes
request.Method = "POST";
var boundary = "---------------------------" +
DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
using (var requestStream = request.GetRequestStream())
{
// Write the values
if (values != null)
{
foreach (string name in values.Keys)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=/"{0}/"{1}{1}", name,
Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
}
// Write the files
if (files != null)
{
foreach (var file in files)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.UTF8.GetBytes(
string.Format("Content-Disposition: form-data; name=/"{0}/"; filename=/"{1}/"{2}", file.Name,
file.Filename, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType,
Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Write(file.Stream, 0, file.Stream.Length);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
}
var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
}
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
responseStream.CopyTo(stream);
return stream.ToArray();
}
}
¿Qué estoy haciendo mal aquí?
EDITAR: localmente está funcionando incluso para el procesamiento de 7-8 minutos. Pero en el entorno en vivo no. ¿Se puede relacionar con la configuración principal de IIS de la aplicación? ¿Se puede relacionar con la configuración del servidor de servicios de Windows?
EDIT 2: configuración del servidor remoto web.config httpRuntime
<httpRuntime enableVersionHeader="false" maxRequestLength="300000" executionTimeout="12000" targetFramework="4.5" />
¿Tal vez se deba al límite de carga de IIS? En IIS7, el valor estándar es de 30 MB. Ver MSDN
EDIT1: Tenga en cuenta que si está cargando varios archivos en 1 solicitud, el tamaño se suma.
EDIT2: en todos los ejemplos de MS siempre hay solo un Stream.Write () . En MSDN se indica: una vez que se ha devuelto el objeto Stream, puede enviar datos con HttpWebRequest utilizando el método Stream.Write. Mi interpretación de esta oración sería que debes llamar a Write () solo una vez. Coloque todos los datos que desea enviar en el búfer y luego llame a Write ().
debería cambiar esta executionTimeout="12000"
a executionTimeout="360000"
que significa cambiar el tiempo de espera de ejecución de 2 minutos a 6 minutos.
Suba sus archivos con un método que cumpla con RFC1867
Y entonces :
UploadFile[] files = new UploadFile[]
{
new UploadFile(fileName1),
new UploadFile(fileName2)
};
NameValueCollection form = new NameValueCollection();
form["name1"] = "value1";
form["name2"] = "xyzzy";
string response = UploadHelper.Upload(url, files, form);
¡Eso es todo amigos!
EDITAR:
Utilizo el método anterior para cargar archivos con más de 100 MB de tamaño, no uso ASP en absoluto, ¡funciona perfecto!
Tuve un problema similar donde la carga funcionaría localmente pero el tiempo de espera en el servidor. Aquí hay dos cosas en juego: supongo que estás hablando de IIS7 +. Si no, avíseme y con mucho gusto borraré mi respuesta.
Entonces, primero está ASP.NET que observa esta configuración (en system.web
):
<!-- maxRequestLength is in KB - 10 MB here. This is needed by ASP.NET. Must match with maxAllowedContentLength under system.webserver/security/requestLimits -->
<httpRuntime targetFramework="4.5" maxRequestLength="1048576" />
Luego está IIS:
<system.webServer>
<security>
<requestFiltering>
<!-- maxAllowedContentLength in bytes - 10MB -->
<requestLimits maxAllowedContentLength="10485760" />
</requestFiltering>
</security>
<system.webServer>
Necesita que estas dos configuraciones estén presentes y que el límite coincida para que las cosas funcionen. Tenga en cuenta que uno está en KB y el otro en bytes.
El problema fue con Azure Load Balancer, que tiene Idle Timeout configurado en 4 minutos por defecto. La nueva publicación del blog de Windows Azure dice que este tiempo de espera ahora se puede configurar al valor entre 4 y 30 minutos
http://azure.microsoft.com/blog/2014/08/14/new-configurable-idle-timeout-for-azure-load-balancer/
Sin embargo, el problema se solucionó con el envío de bytes KeepAlive adicionales a través de TCP, que le indicaron a Load Balancer que no cancelara las solicitudes.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
...
request.Proxy = null;
request.ServicePoint.SetTcpKeepAlive(true, 30000, 5000); //after 30 seconds, each 5 second
Establecer Proxy en nulo (sin usar proxy) es una acción obligatoria aquí, porque de lo contrario el proxy no pasará tcp bytes al servidor.
Puede lograr esta tarea con la técnica AsyncCallback.
¿Qué es AsyncCallback?
Cuando el método async finaliza el procesamiento, se llama automáticamente al método AsyncCallback, donde se pueden ejecutar stmts posteriores al procesamiento. Con esta técnica no hay necesidad de sondear o esperar a que se complete el subproceso asincrónico.
puedes encontrar más detalles en este enlace