This code shows how to convert HTML to PDF in C using the Pdfcrowd API. You can find the tutorial here: https://pdfcrowd.com/blog/convert-html-to-pdf-in-c/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <curl/curl.h> | |
#define API_ENDPOINT "https://api.pdfcrowd.com/convert/latest/" | |
#define USERNAME "demo" | |
#define API_KEY "ce544b6ea52a5621fb9d55f8b542d14d" | |
/* structure for conversion options */ | |
typedef struct { | |
const char *name; | |
const char *value; | |
} FormField; | |
/* structure for conversion files */ | |
typedef struct { | |
const char *name; | |
const char *filename; | |
const char *mime_type; | |
const char *data; | |
size_t data_len; | |
} FormFile; | |
/* structure for conversion response */ | |
typedef struct { | |
char *buffer; | |
size_t size; | |
} ResponseBody; | |
/* write callback to hold the response in a memory buffer */ | |
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *data) | |
{ | |
size_t realsize = size * nmemb; | |
ResponseBody* mem = (ResponseBody*) data; | |
mem->buffer = realloc(mem->buffer, mem->size + realsize + 1); | |
if (mem->buffer == NULL) { | |
fprintf(stderr, "Not enough buffer\n"); | |
return 0; | |
} | |
memcpy(&(mem->buffer[mem->size]), ptr, realsize); | |
mem->size += realsize; | |
mem->buffer[mem->size] = 0; | |
return realsize; | |
} | |
/* conversion function as a multipart post to Pdfcrowd API servers */ | |
long convert(FormField *fields, int num_fields, FormFile *files, int num_files, const char* output_filename) { | |
/* define local variables used */ | |
int i; | |
curl_mime *mime; | |
curl_mimepart *part; | |
struct curl_slist *headers = NULL; | |
ResponseBody response_body = { 0 }; | |
CURLcode res; | |
/* result -1 means error, otherwise it containse HTTP status code */ | |
/* result 200 means success */ | |
/* result greater than 200 means the conversion error, details: https://pdfcrowd.com/api/status-codes/ */ | |
long result = -1; | |
/* initialize CURL library */ | |
CURL *curl = curl_easy_init(); | |
if (!curl) { | |
fprintf(stderr, "Failed to initialize libcurl\n"); | |
return result; | |
} | |
/* set conversion entry point */ | |
curl_easy_setopt(curl, CURLOPT_URL, API_ENDPOINT); | |
/* set Pdfcrowd username and API key */ | |
curl_easy_setopt(curl, CURLOPT_USERPWD, USERNAME ":" API_KEY); | |
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); | |
/* set HTTP multipart post data */ | |
curl_easy_setopt(curl, CURLOPT_POST, 1L); | |
headers = curl_slist_append(headers, "Content-Type: multipart/form-data"); | |
headers = curl_slist_append(headers, "boundary=----------ThIs_Is_tHe_bOUnDary_$"); | |
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); | |
mime = curl_mime_init(curl); | |
for (i = 0; i < num_fields; i++) { | |
part = curl_mime_addpart(mime); | |
curl_mime_name(part, fields[i].name); | |
curl_mime_data(part, fields[i].value, CURL_ZERO_TERMINATED); | |
} | |
for (i = 0; i < num_files; i++) { | |
part = curl_mime_addpart(mime); | |
curl_mime_name(part, files[i].name); | |
curl_mime_filename(part, files[i].filename); | |
curl_mime_type(part, files[i].mime_type); | |
curl_mime_data(part, files[i].data, files[i].data_len); | |
} | |
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); | |
/* set the callback for writting the response into a memory buffer */ | |
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) &response_body); | |
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); | |
/* perform the conversion */ | |
res = curl_easy_perform(curl); | |
if (res != CURLE_OK) { | |
fprintf(stderr, "Failed to perform multipart post: %s\n", curl_easy_strerror(res)); | |
} else { | |
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &result); | |
if (result != 200) { | |
/* print details about the Pdfcrowd error */ | |
fprintf(stderr, "Pdfcrowd Error Code: %ld\n", result); | |
if (response_body.buffer != NULL) { | |
fprintf(stderr, "Pdfcrowd Error Details: "); | |
fwrite(response_body.buffer, 1, response_body.size, stderr); | |
fprintf(stderr, "\n"); | |
} | |
} else { | |
/* success, write the result to the output file */ | |
FILE *fp = fopen(output_filename, "wb"); | |
if (!fp) { | |
fprintf(stderr, "Error opening output file: %s\n", output_filename); | |
} else { | |
if(!fwrite(response_body.buffer, response_body.size, 1, fp)) { | |
fprintf(stderr, "Error writting to file: %s\n", output_filename); | |
result = -1; | |
} | |
fclose(fp); | |
} | |
} | |
} | |
/* do final cleanup */ | |
curl_easy_cleanup(curl); | |
curl_mime_free(mime); | |
curl_slist_free_all(headers); | |
curl_global_cleanup(); | |
return result; | |
} | |
int read_file(const char* filename, FormFile* target) { | |
FILE* fp = fopen(filename, "rb"); | |
long size; | |
char* buffer; | |
size_t bytesRead; | |
/* determine the file size */ | |
fseek(fp, 0, SEEK_END); | |
size = ftell(fp); | |
fseek(fp, 0, SEEK_SET); | |
/* allocate memory for the file contents */ | |
buffer = (char*) malloc(size); | |
if (buffer == NULL) { | |
fprintf(stderr, "Error: could not allocate memory\n"); | |
fclose(fp); | |
return 1; | |
} | |
/* read the file into memory */ | |
bytesRead = fread(buffer, 1, size, fp); | |
if (bytesRead != (size_t) size) { | |
fprintf(stderr, "Error: could not read file\n"); | |
free(buffer); | |
fclose(fp); | |
return 1; | |
} | |
fclose(fp); | |
target->name = "file"; | |
target->filename = filename; | |
target->mime_type = "application/octet-stream"; | |
target->data = buffer; | |
target->data_len = size; | |
return 0; | |
} | |
long convert_url_example() { | |
FormField* fields = malloc(sizeof(FormField) * 4); | |
fields[0].name = "input_format"; | |
fields[0].value = "html"; | |
fields[1].name = "output_format"; | |
fields[1].value = "pdf"; | |
fields[2].name = "page_size"; | |
fields[2].value = "letter"; | |
fields[3].name = "url"; | |
fields[3].value = "https://example.com/"; | |
return convert(fields, 4, NULL, 0, "example_url.pdf"); | |
} | |
long convert_text_example() { | |
FormField* fields = malloc(sizeof(FormField) * 4); | |
fields[0].name = "input_format"; | |
fields[0].value = "html"; | |
fields[1].name = "output_format"; | |
fields[1].value = "pdf"; | |
fields[2].name = "page_size"; | |
fields[2].value = "letter"; | |
fields[3].name = "text"; | |
fields[3].value = "<h1>Hello from Pdfcrowd</h1>"; | |
return convert(fields, 4, NULL, 0, "example_text.pdf"); | |
} | |
long convert_file_example() { | |
FormFile* files; | |
FormField* fields = malloc(sizeof(FormField) * 3); | |
fields[0].name = "input_format"; | |
fields[0].value = "html"; | |
fields[1].name = "output_format"; | |
fields[1].value = "pdf"; | |
fields[2].name = "page_size"; | |
fields[2].value = "letter"; | |
files = malloc(sizeof(FormFile)); | |
if(read_file("your-file.html", &files[0])) { | |
fprintf(stderr, "Error reading file\n"); | |
return -1; | |
} | |
return convert(fields, 3, files, 1, "example_file.pdf"); | |
} | |
int main() { | |
if(convert_url_example() != 200) { | |
fprintf(stderr, "url test failed\n"); | |
return -1; | |
} | |
if(convert_text_example() != 200) { | |
fprintf(stderr, "text test failed\n"); | |
return -1; | |
} | |
if(convert_file_example() != 200) { | |
fprintf(stderr, "file test failed\n"); | |
return -1; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment