Ver Mensaje Individual
  #5 (permalink)  
Antiguo 02/02/2010, 13:24
jmo25
 
Fecha de Ingreso: febrero-2010
Mensajes: 3
Antigüedad: 14 años, 9 meses
Puntos: 0
Respuesta: POST en vb.net

Hola.

Recorriendo varios foros encontré este problema, voy a intentar ser lo más claro posible. El problema principal es que no hay muchos ejemplos y los que hay son poco claro.

Para abordar este tema hay que tener en cuenta las necesidades de cada aplicación y la configuración del servidor al que vamos a enviar el archivo

De la aplicación tener en cuenta
  • Si se envía datos de cadena solamente
  • Si se envía archivo/s
  • Utiliza buffer de escritura

Del servidor tener en cuanta
  • Que protocolo utiliza
    • Si es a través de HTTPS (SSL) requiere que revisemos el certificado del servidor
  • Que tipo de autenticación utiliza
    • Anónima
    • Integrada
      • Debemos pasarle las credenciales de conexión o indicarle que utilice las por defecto
    • Básica
      • Indicarle en el head del post el usuario y la contraseña

Certificado del servidor

Cuando la conexión se realiza a través de HTTPS el objeto HttpWebRequest va a requerir una función que valide el certicado del servidor.
¿Como se hace?
1) Crear la función que analiza el certificado
Código vb:
Ver original
  1. Private Function ValidateCertificate(ByVal sender As Object, ByVal      certificate As X509Certificate, ByVal chain As X509Chain, ByVal sslPolicyErrors As SslPolicyErrors) As Boolean
  2.         Dim resultado As Boolean
  3.         resultado = True
  4.         '
  5.        ' Analizar el certificado y devolver true o false según sea el caso
  6.        '
  7.        Return resultado
  8.     End Function
2) Asignar la misma al “ServicePointManager”

Código vb:
Ver original
  1. ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateCertificate)


Autenticación
Según el tipo de autenticación requerida por el servidor utilizaremos alguno de los siguiente códigos, hay otras formas de asignar las credenciales, les dejo las que me parecen las más simples

Autenticación Anónima
Podemos obviar el codigo o indicarle que utilizaremos las credenciales por defecto
Código vb:
Ver original
  1. HttpWRequest.Credentials = CredentialCache.DefaultCredentials

Autenticación integrada
Debemos darle las credenciales apropiadas

Código vb:
Ver original
  1. Dim creds As New Net.NetworkCredential(USERNAME, PSSWD, Domain)
  2. HttpWRequest.Credentials = creds

Buffer de escritura
Otro tema a tener en cuenta es si la escritura se realiza directamente al flujo de salida o se retiene en buffer para luego ser enviado.
Para la mayoría de las aplicaciones es más cómodo utilizar el buffer ya que nos permite manejar de forma más simple los errores, la escritura directa se utiliza para envíos de stream, para enviar archivos de gran tamaño con control de progreso en el envío, etc.
Código vb:
Ver original
  1. HttpWRequest.AllowWriteStreamBuffering = True

Enviar datos
Ahora si, pasado el certificado y la autenticación ahora vamos a enviar los datos.
Primero tener en cuenta que si se van a enviar archivos se debe utilizar el contentType=”multipart/form-data” que es distinto de cuando se envía solamente cadenas (contentType=”application/x-www-form-urlencoded” )

Enviar solamente cadenas
Cuando se requiere enviar datos de cadena hay que generar una cadena igual a la del metodo “GET“, que en lugar de concatenarla a la URL se envía por “POST”.
Vi algunas implementaciones donde envían archivos como cadenas codificados en base64, si bien en principio esto funciona no lo recomiendo ya que para eso esta el otro enctype (multipart/form-data)
Código vb:
Ver original
  1. HttpWRequest.Method = "POST"
  2. HttpWRequest.ContentType = "application/x-www-form-urlencoded"
  3. 'Generar cadena igual que para el metodo get
  4. Dim data As StringBuilder = New StringBuilder()
  5. data.Append("param01=" + HttpUtility.UrlEncode("valor01"))
  6. data.Append("&param02=" + HttpUtility.UrlEncode("valor02"))
  7. data.Append("&param03=" + HttpUtility.UrlEncode("valor03"))
  8.  
  9. 'Crear array de bytes de la cadena  
  10. Dim byteData() As Byte
  11. byteData = UTF8Encoding.UTF8.GetBytes(data.ToString())
  12. 'Setear el largo del stream  
  13. HttpWRequest.ContentLength = byteData.Length
  14. 'Escribir datos
  15. Dim postStream As Stream = Nothing
  16. postStream = wr.GetRequestStream()
  17. postStream.Write(byteData, 0, byteData.Length)
  18.  
  19. 'Enviar los datos (si buffer está activado) y recuperar la respuesta
  20. Dim Response As HttpWebResponse
  21. Response = wr.GetResponse()

Enviar archivos

Para enviar archivo se debe utilizar el contentType “multipart/form-data” del método “POST” esta codificación es una estructura de datos que permite incluir en la misma el contenido de los archivo. Es la que utilizan los exploradores para enviar archivos cuando se crean los forms con input de tipo file.

Código HTML:
Ver original
  1. <form name="formDocs" method="post" action="pagina.asp" enctype="multipart/form-data">
  2.         <input type="hidden" name="param01" value="valor01"/>
  3.         <input type="file" name=" archivo" />
  4.         <input type="submit" />
  5. </form>

Este el el código
Código vb:
Ver original
  1. Dim LocalFile As String = "c:\archivo_a_enviar.txt"
  2. HttpWRequest.Method = "POST"
  3. 'Hay que generar un limite y asegurarnos que sea único
  4. 'Por ejemplo
  5. Dim limite As String = "----------" & DateTime.Now.Ticks.ToString("x")
  6. HttpWRequest.ContentType = "multipart/form-data; boundary=" & limite
  7.  
  8. Dim sb As StringBuilder = New StringBuilder()
  9. 'Por cada parametro hay que generar una estructura que varía
  10. 'si es de archivo o no
  11.  
  12. 'Parámnetro de cadena
  13. sb.Append("--")
  14. sb.Append(limite)
  15. sb.Append(vbNewLine)
  16. sb.Append("Content-Disposition: form-data; name=""")
  17. sb.Append("param01")
  18. sb.Append("""")
  19. sb.Append(vbNewLine)
  20. sb.Append(vbNewLine)
  21. sb.Append("param_valor01")
  22. sb.Append(vbNewLine)
  23.  
  24. 'Parámnetro de archivo
  25. sb.Append("--")
  26. sb.Append(limite)
  27. sb.Append(vbNewLine)
  28. sb.Append("Content-Disposition: form-data; name=""")
  29. sb.Append("sampfile")
  30. sb.Append("""; filename=""")
  31. sb.Append(Path.GetFileName(LocalFile))
  32. sb.Append("""")
  33. sb.Append(vbNewLine)
  34. sb.Append("Content-Type: ")
  35. sb.Append("application/octet-stream")
  36. sb.Append(vbNewLine)
  37. sb.Append(vbNewLine)
  38.  
  39. 'pasamos la cadena a matriz de bytes
  40. Dim postHeader As String = sb.ToString()
  41. Dim postHeaderBytes As Byte() = Encoding.UTF8.GetBytes(postHeader)
  42.  
  43. 'Crear la string de límite final como matriz de bytes
  44. Dim limiteBytes As Byte() = Encoding.UTF8.GetBytes(vbNewLine & "--" + limite + vbNewLine)
  45.  
  46.  
  47. 'Crear un stream con el archivo
  48. Dim fileStream As FileStream = New FileStream(LocalFile, FileMode.Open, FileAccess.Read)
  49.  
  50. 'Calcular el largo del contenido
  51. Dim length As Long = postHeaderBytes.Length + fileStream.Length + limiteBytes.Length
  52. HttpWRequest.ContentLength = length
  53.  
  54. Dim stream As Stream = wr.GetRequestStream()
  55. 'Escribir cabecera
  56. stream.Write(postHeaderBytes, 0, postHeaderBytes.Length)
  57. 'Escribir contenido del archivo
  58. Dim buffer As Byte() = {}
  59. ReDim buffer(fileStream.Length - 1)
  60.  
  61. Dim bytesRead As Integer = 0
  62. bytesRead = fileStream.Read(buffer, 0, buffer.Length)
  63. While bytesRead <> 0
  64.   stream.Write(buffer, 0, bytesRead)
  65.   bytesRead = fileStream.Read(buffer, 0, buffer.Length)
  66. End While
  67.  
  68. 'Escribir el límite final
  69. stream.Write(limiteBytes, 0, limiteBytes.Length)
  70.  
  71. 'Enviar los datos (si buffer está activado) y recuperar la respuesta
  72. Dim Response As HttpWebResponse
  73. Response = wr.GetResponse()

Última edición por jmo25; 02/02/2010 a las 13:56