0

So, im making a webserver in C that display a sensor temperature and also a plot made with gnuplot in png format. Im having problem sending the http template and the png image. I can send the http template with all the data but cant attach the image in the end.

static const char response_http_template[] = {
    "HTTP/1.1 200 OK \
Date: Mon, 27 Jul 2009 12:28:53 GMT \
Server: Apache/2.2.14 (Win32) \
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT \
Content-Length: %lu \
Content-Type: text/html \
Connection: Closed \
\n\n \
%s \
%s"
};

static const char response_page_template[] = {
    "<!DOCTYPE html> \
<html> \
<head> \
    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /> \
    <meta charset=\"utf-8\" /> \
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> \

more html code with some %s
}

void send_response_data(uint32_t sock_client,
                        const char *student_name,
                        last_temp_t *last_temp)
{
    char write_buf[8192] = { 0 };
    char out_buf[8192] = { 0 };

    struct stat filestat;
    char filesize[7];
    int fd;
    char file_buf[1024] = {0};
    char result;
    FILE *fp;

    if ( ((fd = open ("./sup/data.png", O_RDONLY)) < -1) || (fstat(fd, &filestat) < 0) ) {
        printf ("Error in measuring the size of the file");
    }

    sprintf (filesize, "%zd", filestat.st_size);
    printf("File size %s\n", filesize);

    fp = fopen ("./sup/data.png", "r"); 
    if (fp == NULL) 
    { 
        perror("fopen error");
        exit(EXIT_FAILURE);
    }

    fread(file_buf, sizeof(char), filestat.st_size + 1, fp);
    fclose(fp);

    sprintf(
      write_buf, response_page_template, student_name, last_temp->timestamp, last_temp->temp);
    sprintf(out_buf, response_http_template, strlen(write_buf) + strlen(file_buf), write_buf, file_buf);
    write(sock_client, out_buf, strlen(out_buf));

}

When i start a client with chrome, i see the http code correct, but the image is not showed, only text like this: �PNG

Any ideas on how to send the binary data? Or if i need to change something in the http templates?

Thanks

rockstiff
  • 355
  • 1
  • 2
  • 17
  • You should send image separately of html by browser's reqeust (which initiated by `` tag) and specify `Content-Type` header for it like `image/png`. Browser can't render inline png. But you can use svg if you want inline image. – Feo Nov 14 '19 at 14:46
  • Normally, the HTML page contains a reference to the graphics image, and the browser retrieves the image using a separate request. – Bodo Nov 14 '19 at 14:46
  • @Bodo can't i send both in a single request? All i do in chrome is enter the url and press F5 everytime i need an updated value/image – rockstiff Nov 14 '19 at 15:02
  • Did you send a content-type? – user253751 Nov 14 '19 at 17:00

1 Answers1

1

There are two possible paths here:

  1. Check the request URL, and based on the URL either send the HTML page, or the image, OR
  2. Combine both using data URL

For option #1, the 'main' server will have to check if the URL points to /image/ (or other folder that will represent the images).

For option #2, Data URL (google it, or look at: https://en.wikipedia.org/wiki/Data_URI_scheme

img src="data:image/png;base64,iVBORw0KGgoAAA
ANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4
//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU
5ErkJggg==" alt="Red dot" />

You will need base64 encoder to convert the file from binary to text.

dash-o
  • 13,723
  • 1
  • 10
  • 37
  • I need option #2. So i have to read the binary data from the image, convert it to base64 and then embed it to the http template? – rockstiff Nov 14 '19 at 15:27
  • Yes, that's it. Assuming image is not VERY large, all browsers will deal with it. 2MB PNG size is OK, per https://stackoverflow.com/questions/695151/data-protocol-url-size-limitations – dash-o Nov 14 '19 at 15:56
  • It worked! I was able to found a simple base64 encoder and embed the data in the html template with no problem. Thanks! – rockstiff Nov 15 '19 at 13:51