Enviar un archivo a un servidor

Iniciado por Vaagish, 5 Febrero 2014, 19:43 PM

0 Miembros y 4 Visitantes están viendo este tema.

Vaagish

Hola amigos,, puse esta consulta acá, y aunque parece simple creo que no lo es,, tanto..

La cosa es así,, tengo que enviar un archivo mediante POST a un servidor, desde un socket (winsock) conectado previamente.. así que supongo que lo que tengo que enviar es un array,, al estilo formulario HTML!

Para los que también entiendan de PHP la cosa es así:

Código (php) [Seleccionar]
$tmp_name = $_FILES["pictures"]["tmp_name"];
move_uploaded_file($tmp_name, $SaveAs);


$_FILES es un array que recibe la información para saber como guardarla en el servidor,, el asunto es que yo con C++ no puedo enviar un array,, o si?

Aparte, no estoy seguro si se tiene que enviar el array con la información y nada mas o lleva algún encabezado HTTP..

Saludos!!

PD: Puse este tema acá en C++, porque creo que lo mas complicado va a ser armar todo desde el cliente,, si no tengo resultados acá, movemos el tema a WEB y vemos que pasa...

Yoel Alejandro

#1
Sí se puede, aunque yo personalmente no lo he intendao (quiero hacerlo en un futuro). Hay una biblioteca de socktes, no se dónde se ubique en sistemas Windows pero en GNU/Linux es <sys/socket.h> y posiblemente haya que añadir <sys/wait.h> y <netinet/in.h>

Luego debes usar algunas funciones como socket, bin, listen (esto en LINUX pero creo que es igual para Windows). En la página http://www.chuidiang.com/clinux/ busca el apartado de sockets y te explican paso a paso cómo debes hacerlo y qué funciones debes usar. Incluso incluyen un ejemplo resuelto, con el código fuente y todo (en Español).

Espero te sirva y ayude ...

====================
Por cierto, como todo esto es para Linux, si quieres que sea compatible con Windows (si es tu caso) usa un compilador de C de GNU para Windows, así muchas de las funciones de GNU funcionarán correctamente en Windows. Descárgate MinGW de la página http://www.mingw.org/ y busca la ruta del ejecutable gcc.exe, luego la añades a la variable de entorno PATH y ya puedes compilar con este compilador de GNU. Si quieres más detalles de cómo hacerlo dime y te indico.

Es posible que si usas otro compilador como el de BorlandC (estoy especulando, la verdad no se a ciencia cierta) no te funcionen los ejemplos para Linux dados en chuidiang.com
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

cpu2

Cita de: Vaagish en  5 Febrero 2014, 19:43 PMel asunto es que yo con C++ no puedo enviar un array,, o si?

Pues con send o sendto, tienes la informacion en la msdn, y si quieres crear un socket con mas opciones tienes setsockopt y getsockopt.

Un saludo.

Vaagish

Hola! Gracias por responder!

Si,, yo los sockets los manejo,, ya pude enviar request simples con información,, el asunto es enviar una imagen, por post.. me gustaría saber como es que un formulario envía la información, y luego recrear esa situación (el envio del formulario) pero con sockets, en C++..

Como puse por ahi,, la conexión la tengo,, y el envio de texto/variables también, pero para las imágenes se hace algo diferente,,

Así se puede enviar un string con el request al servidor..

Código (cpp) [Seleccionar]
char HTTPStr[37] = "POST /Proyectos/Uploads/upload.php?";
char HTTPEnd[34] = "HTTP/1.1\nhost: localhost\r\n\r\n";


en el medio de esas dos cadenas debería ir el contenido de la request

cpu2

Bueno como bien dijiste tu, no se si tendran que mover esto al subforo de programacion web, creo que hay te ayudaran mejor.

Navegando un poco, encontre estos code.

http://stackoverflow.com/questions/14728125/how-do-i-send-an-image-over-http-protocol-in-c
http://www.dreamincode.net/forums/topic/203610-simple-http-sending-images-jpeggif/


En el ejemplo que muestras tu, creas el encabezado con esas "definiciones" (vamos a llamarlas asi) POST y HTTP/1.1, en esos ejemplos las definiciones son mas extensas, supongo que seria encontrar la definicion adecuada y crear el encabezado correcto y enviar el paquete.

Un saludo.


Yoel Alejandro

Que bueno que puedas resolver con eso!!!

Por si acaso te sirve, el envío de un formulario a un servidor consiste simplemente de un mensaje HTTP de tipo GET o un POST, que en su cuerpo contiene parejas de nombre-valor. El atributo "name" de cada control del formulario seguido se su "value".

En el caso de imágenes es igual, pero el contenido del mensaje es simplemente el flujo de bits que forma la imagen. Es decir, el contenido bruto del fichero de imagen. Pero en la cabecera del mensaje debes especificar el tipo MIME del documento, que por ejemplo para una imagen GIF debe ser  "image/gif"
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)

Vaagish

CitarInsertar Cita
Que bueno que puedas resolver con eso!!!

Por si acaso te sirve, el envío de un formulario a un servidor consiste simplemente de un mensaje HTTP de tipo GET o un POST, que en su cuerpo contiene parejas de nombre-valor. El atributo "name" de cada control del formulario seguido se su "value".

En el caso de imágenes es igual, pero el contenido del mensaje es simplemente el flujo de bits que forma la imagen. Es decir, el contenido bruto del fichero de imagen. Pero en la cabecera del mensaje debes especificar el tipo MIME del documento, que por ejemplo para una imagen GIF debe ser  "image/gif"

Gracias por tu respuesta! Estuve leyendo sobre el tema y es asi como decis.. ahora estoy tratando de esnifar los paquetes con un programa,, en cuanto consiga la cadena correcta la posteo aca!

Saludos!

Vaagish

#8
Bueno,, después de muchas horas de lucha,, no lo he conseguido.. voy a dejar el código de la parte que tendría que hacer la magia,, pero no la hace..

Código (cpp) [Seleccionar]
#include "main.h"
#include "conexion.h"

#include <iostream>
using namespace std;

char A[64] = "POST /Proyectos/Uploads/uploader.php HTTP/1.1\nhost: localhost\r\n";
char B[27] = "Content-type: image/jpeg\r\n";
char C[23] = "Content-Length: 3024\r\n";
char D[3] = "\r\n";

char ConnString[] = "";


int main()
{

SOCKET Sock = Conectar();
HANDLE Rec_Handle = CreateThread(NULL, 0, Recibir, NULL, NORMAL_PRIORITY_CLASS, NULL);

// ARCHIVO
FILE *Archivo;
char Buff[3024];
Archivo = fopen("auto.jpg", "rb");
int Tamano = fread(Buff, 1, 3024, Archivo);
fclose(Archivo);
// ******************************************

strcat(ConnString, A);
strcat(ConnString, B);
strcat(ConnString, C);
strcat(ConnString, D);

int Total = strlen(ConnString) + Tamano;

strcat(ConnString, Buff);

send(Sock, ConnString, Total, 0);

cin.get();
return 0;
}


Asumimos que en conexion.cpp estan las funciones para conectarse (cosa que hace bien) y devuelve un SOCKET (para poder usar send luego en main.cpp), tambien esta la funcion recibir, que se inicia como un hilo, y que tambien funciona bien,, porque del servidor me llega "Ha ocurrido un error, la imagen no se subio", con las respectivas cabeceras HTTP. Bueno,, probablemente el error este en mi cabecera HTTP, que esta formada por A,B,C y D.. No puedo mas con esto jajaja

Saludos!!

EDIT: Me parece que no se debe utilizar strcat con archivo binarios... Sugerencias para unir un puntero char con datos binarios??

EDIT: Ya arregle con memcpy el item anterior..

cpu2

La funcion strcat trabaja con cadenas, eso significa que al encontrar un valor nulo 0, esta dejara de copiar, y a ser un valor binario segurisimo que hay un 0.

Tendrias que usar memcpy, prueba si funciona, si no tendrias que repasar esas cabzeras, y bueno no estoy muy metido en C/C++ pero los punteros se podrian arreglar y todas esas funciones tambien.

Un saludo.