Error codificacion de caracteres? HTTP Download

Iniciado por Vaagish, 1 Octubre 2013, 22:36 PM

0 Miembros y 1 Visitante están viendo este tema.

Vaagish

Buenas amigos! Alguien sabe porque no se pueden escribir ciertos caracteres con fopen? Aqui dejo el code y el error al final del mismo


#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#pragma comment(lib, "ws2_32.lib")

#include <iostream>
using namespace std;

#define DEFAULT_BUFLEN 1
#define PORT 80

WSADATA WSA;
SOCKET Socket;
SOCKADDR_IN Server;
HOSTENT *Info;
FILE *MyFile;

char *IP;

int Bytes;
char Buffer[DEFAULT_BUFLEN];
int Bufflen = DEFAULT_BUFLEN;

DWORD WINAPI Descargar (void* Nada);

DWORD WINAPI Descargar (void* Nada)
{

do {

Bytes = recv(Socket, Buffer, Bufflen, 0);

if(Bytes > 0){
fputs(Buffer, MyFile);
}

}while(Bytes > 0);

fclose(MyFile);
return 0;
}

int main()
{

char *Request = "GET /img/cpp-logo.png HTTP/1.1\nhost: www.cplusplus.com\r\n\r\n";
    unsigned int j = 0;

MyFile = fopen("C:\\Imagen.txt","w");
int Res;

WSAStartup(MAKEWORD(2, 2), &WSA);
    Socket = socket(AF_INET, SOCK_STREAM, 0);
   
    Info = gethostbyname("www.cplusplus.com");

IP = inet_ntoa(*(struct in_addr*)(Info -> h_addr_list[0]));

    Server.sin_family = AF_INET;
    Server.sin_port = htons(PORT);
Server.sin_addr.s_addr = inet_addr(IP);

connect(Socket, (struct sockaddr*)&Server, sizeof(Server));
     
    send(Socket, Request, strlen(Request), 0);

HANDLE Hand = CreateThread(NULL, 0, Descargar, NULL, NORMAL_PRIORITY_CLASS, NULL);

cin.get();
closesocket(Socket);
    return (EXIT_SUCCESS);
}


Bueno, el problema es que la respuesta del servidor es:

HTTP/1.1 200 OK

Date: Tue, 01 Oct 2013 20:24:42 GMT

Server: Apache/2.2.3 (CentOS)

Last-Modified: Tue, 08 Mar 2011 09:51:17 GMT

ETag: "2b60065-2434-49df58db76f40"

Accept-Ranges: bytes

Content-Length: 9268

Connection: close

Content-Type: image/png



‰PNG



IHDRÆKkitEXtSoftwareAdobe ImageReadyqÉe<PLTEˆÍgüõÿñëÿ‹Ì...ƒ{©': ETC, ETC...(IMAGEN PNG)


Bueno, con el editor de texto borro todo lo que tiene que ver con HTTP, pero aun asi, al abrir con el editor de texto la imagen descargada con el navegador web, veo que no es igual la codificacion, al parecer no "reconoce" ciertos caracteres al guardarlos en el archivo de texto, y corrompe el archivo.. Como podria solucionar esto ?? :/

Gracias!

Vaagish

#1
Ahora que profundizo un poco mas en el code, me doy cuenta que me cambia todos los "\r\n" por "\n" o sea, el png original tiene "\r\n" y el mio solo "\n" como fin de linea... :/

tengo que recorrer el code y cambiarlo "a mano" ??

EDITADO:

Pff,, Ahora entiendo que esto tiene que ver con el formato Unix y Windows... Estoy por enfermar,, podria funcionar algo asi? Que les parece?

DWORD WINAPI Descargar (void* Nada)
{
char * Pos;

do{
     Bytes = recv(Socket, Buffer, Bufflen, 0);
   
    Pos = strstr(Buffer,"\r");
    if(Pos){
strncpy(Pos,"\r\n",4);
    }

    fwrite(Buffer, 1, Bytes, MyFile);

}while(Bytes > 0);

return 0;
}

eferion

Supongamos que te llega ABC\nDEF

Tu strncpy dejaría la cadena tal que: ABC\r\n\EF

strncpy( Pos, "\r\n", 4 ) no desplaza lo que haya detrás... lo sobreescribe.

En cualquier caso, si tu quieres recuperar la imagen, y solo la imagen, tienes que eliminar toda la cabecera http que te envía el servidor y quedarte únicamente con el código de la imagen.

La respuesta del servidor no va a generar por si sola una imagen válida, ya que la cabecera http no está contemplada en ningún estándar de ficheros de imagen.

rir3760

La función "Descargar" la puedes acortar a:
Código (cpp) [Seleccionar]
DWORD WINAPI Descargar(void *Nada)
{
   int num_bytes;
   
   while ((num_bytes = recv(Socket, Buffer, Bufflen, 0)) > 0)
      fwrite(Buffer, 1, num_bytes, MyFile);

   return 0;
}


También debes abrir el archivo en modo binario con "wb" y falta cerrarlo llamando a fclose.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Vaagish

#4
Gracias por las respuestas! La cabecera HTTP la pensaba eliminar con alguna funcion de cadenas, eso no me preocupa mucho.. el problema es la codificacion.. se supone que yo deba solucionarlo con codigo? me parece raro, porque es un archivo, no un texto.. no deberia de respetar el contenido del archivo binario tal cual es? sino como es que se pueden abrir archivos de imagen tanto en linux como en windows??? No lo entiendo..

Gracias!

EDITADO: Listo! El problema era abrir el archivo como "w+" y no como "wb" como dice rir3760! Gracias again! :D

eferion

Los archivos de imagen se basan en un estándar. Dicho estándar rige las normas de codificación. Entre esas normas se detallan los posibles saltos de línea.

Tu piensa que estos estándares van ligados al formato, no al sistema operativo, lo que permite que la imagen se pueda abrir y guardar sin problemas en cualquier sistema operativo.

Vaagish

A modo de completar el tema.. por si alguien se ve en la misma situación.. para poder cortar la cabecera HTTP se puede buscar la siguiente secuencia (al menos en archivos binarios) "\r\n\r\n" pues entre la cabecera y la información binaria se dejan 2 espacios  ::)

Saludos!