Thread: How can I download an Image from the web

  1. #1
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266

    How can I download an Image from the web

    Say I have some socket application that uses SOCK_STREAM, is there a way to send an HTTP GET request to receive an image? How would I store that image in the program? Would it be in a character array or something? I'd imagine that it would have to be a pretty big array.

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    If I remember correctly, this question has been answered before on the forum with a complete working example. I suggest doing a forum search to see what you can find.
    bit∙hub [bit-huhb] n. A source and destination for information.

  3. #3
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Binary data == array of bytes. You should be able to issue a HTTP HEAD command for the image URL to get the size of the image, then allocate memory for the array, then use GET to retrieve the data into the array.

    Code:
    curl -I http://www.cprogramming.com/cprog.png
    HTTP/1.1 200 OK
    Date: Fri, 17 Sep 2010 00:41:04 GMT
    Server: Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.9
    Last-Modified: Sat, 28 Aug 2010 14:06:47 GMT
    ETag: "4cf0ca4-1db1-48ee2bdecabc0"
    Accept-Ranges: bytes
    Content-Length: 7601
    Content-Type: image/png
    Code:
    curl -v -o output.txt http://www.cprogramming.com/cprog.png
    * About to connect() to www.cprogramming.com port 80 (#0)
    *   Trying 76.74.255.245... connected
    * Connected to www.cprogramming.com (76.74.255.245) port 80 (#0)
    > GET /cprog.png HTTP/1.1
    > User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
    > Host: www.cprogramming.com
    > Accept: */*
    > 
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
      0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0< HTTP/1.1 200 OK
    < Date: Fri, 17 Sep 2010 00:43:20 GMT
    < Server: Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.9
    < Last-Modified: Sat, 28 Aug 2010 14:06:47 GMT
    < ETag: "4cf0ca4-1db1-48ee2bdecabc0"
    < Accept-Ranges: bytes
    < Content-Length: 7601
    < Content-Type: image/png
    < 
    { [data not shown]

  4. #4
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Thanks rags, that clears some things up. I will start this project tonight because I think it would be fun. Probably wont take very long though.

    Also bithub: I found a link to a previous thread, thanks! Downloading a file via HTTP?

  5. #5
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by rags_to_riches View Post
    Binary data == array of bytes. You should be able to issue a HTTP HEAD command for the image URL to get the size of the image, then allocate memory for the array, then use GET to retrieve the data into the array.
    The problem is that the server may be using Chunked encoding. If so, it won't return the size of the returned content. This is why it's usually better to use a library like libcurl than to write your own HTTP client.
    bit∙hub [bit-huhb] n. A source and destination for information.

  6. #6
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Totally agree, and that was in my first draft. Where the standard protocols are concerned, it is of course always better to go with a tried-and-tested existing library. Where the OP specifically mentioned doing it with sockets, I figured I'd at least help with that.

  7. #7
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Is there another way other than using sockets?

  8. #8
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Syscal View Post
    Is there another way other than using sockets?
    Well, you could try yelling at it... but it might not respond very well.

    Winsock is a computer's connection to the world.

  9. #9
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Yes, as bithub mentioned, libcurl. Or where you're on Windows there's winhttp.
    Last edited by rags_to_riches; 09-17-2010 at 07:09 AM.

  10. #10
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    So I started out just by trying to copy a file that is on my own system. The code works, it can copy an image but my problem when I want to use some block reading function like fread or fwrite. Why wont the image copy? When I use fread/write the file isn't the same size as the original. My method of writing on a character by character basis may be slow, but it works. So can someone tell me why the commented code wont work for an image? It does for text files but not images.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    void error(char *err){
    	printf("%s\n",err);
    	exit(-1);
    }
    
    char *get_copy(char* filename){
    
    	int i = 0;
    	char *file = malloc(strlen(filename) + strlen("_copy.ext"));
    	while(*filename != '.') file[i++] = *filename++;
    	strcat(file,"_copy");
    	strcat(file,filename);
    	
    	return file;
    }
    
    int main(int argc, char *argv[]){
    
    	if(argc != 2){
    		char err_msg[32];
    		snprintf(err_msg,sizeof(err_msg),"Usage: %s <file_to_copy>",argv[0]);
    		error(err_msg);
    	}
    		
    	
    	FILE *ifile, *ofile;
    	char *out_file, c;
    	int file_size = 0, nread = 0;
    	
    	if(!(ifile = fopen(argv[1], "r")))
    		error("Error opening read file");
    	
    	out_file = get_copy(argv[1]);
    	
    	fseek(ifile,0,SEEK_END);
    
    	file_size = ftell(ifile);
    	
    	fseek(ifile,0,SEEK_SET);
    	 
    	if(!(ofile = fopen(out_file,"w")))
    		error("Error opening write file");
    
    	printf("Writing %d bytes to %s\n", file_size ,out_file);
    	
    	while(nread < file_size){
    		c = fgetc(ifile);
    		fputc(c,ofile);
    		nread++;
    	}
    
    	printf("%d bytes written to %s\n",nread, out_file);
    
    	fclose(ifile);
    	fclose(ofile);
    	
    	return 0;
    }
    Last edited by Syscal; 09-17-2010 at 10:22 PM.

  11. #11
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    And if you don't think it works, I took a screen shot.

    http://img339.imageshack.us/img339/7...eenshotahc.png

  12. #12
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67
    Just a small note, you forgot to free(out_file) in main.....


  13. #13
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    So can someone tell me why the commented code wont work for an image?
    What commented code?

    You should be opening the files in binary mode ("rb"/"wb", nor "r"/"w")

    This code:
    Code:
    char *get_copy(char* filename){
            int i = 0;
    	char *file = malloc(strlen(filename) + strlen("_copy.ext"));
    	while(*filename != '.') file[i++] = *filename++;
    	strcat(file,"_copy");
    	strcat(file,filename);
    	
    	return file;
    }
    can be greatly improved by the following:
    Code:
    char *get_copy(char* filename){
    
        // You forgot space for the null terminator
        char *file = malloc(strlen(filename) + strlen("_copy.ext") + 1);
        if (file) {
            sprintf(file, "%s_copy.ext", filename);
        }
        return file;
    }
    Yay for boobs in the screenshot...cheers!
    Last edited by rags_to_riches; 09-18-2010 at 09:30 AM.

  14. #14
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Hahahaha, I would have used other images but those were the only ones on the computer I used to write the code. And the router is downstairs and this particular machine has no wireless nic nor do I have a really long ethernet cable. I finally had decided to share my laptops internet connection so thats why it shows that I have a connection in that screenshot. Also rags, the reason my get_copy() is the way it is is because I append the file extension to the _copy filename. The extension shouldn't be ".ext". I just wanted to allocate enough space for the "up to three letter" extension. You know, .c, .mp4 or .jpg. Otherwise, the file would be misinterpreted, wouldn't it? I mean, what uses the extension ".ext"?


    Example: if I supplied socket.c as argv[1] using my code would produce the copy file as "socket_copy.c". Yours would produce "socket_copy.ext". I intentionally wrote it this way. Do you know of a better way to get the extension or is what I have done fine?

    EDIT: disregard that statement about the commented code. I took it out. I think i may be getting undesired results because I forgot to make the buffer unsigned. Could that be part of the problem?
    Last edited by Syscal; 09-18-2010 at 11:14 AM.

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    Code:
    mr. the dude.jpeg
    The actual name of a file on my server.

    I'm just tossing the example out.

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. capturing image from web cam
    By sravanthidesu25 in forum C++ Programming
    Replies: 1
    Last Post: 03-16-2010, 10:43 AM
  2. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  3. HotSpot image controls (web)
    By novacain in forum C# Programming
    Replies: 0
    Last Post: 06-25-2008, 04:27 AM
  4. download free bsd image?
    By iain in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 10-11-2002, 10:10 AM