C 使用 CURL 获取文件
C getting a file using CURL
我正在尝试使用 CURL Lib 通过 C 包装器从我的 Amazon S3 获取图像和 PDF 文件,目前我可以获得类似 txt 文件、类似错误的 HTTP HTML 响应,但是当我尝试获取我收到的 PDF 和 JPEG 文件作为响应:
(DEBUG) Size : 90343
(DEBUG) Response : ����
我不知道这些奇怪的字符是从哪里来的,但我怀疑我需要添加CURLOPT_BINARYTRANSFER
下面是使用 CURL 的 HTTP GET 函数和定义:
const char *url = "http://bucket.s3.amazonaws.com/file.pdf";
long rc;
struct buf_string response = {0};
rc = http_get(url, &response, (const char *[]){"Accept: */*", "Accept-Encoding: gzip, deflate", "User-Agent: web-service/0.1", NULL});
if (rc != 200) { /* error */ }
logprintf(ts, D_DEBUG, "Size : %d", response.pos);
logprintf(ts, D_ERROR, "Response : %s", response.buf);
long
http_get(const char *url, struct buf_string *response, const char *headers[]) {
struct http *h = http_create();
long rc;
h->method = "GET";
h->url = url;
h->headers = headers;
if (response) {
memset(response, 0, sizeof(*response));
h->response_body = response;
h->write_function = default_write_data;
}
rc = http_perform(h);
http_free(h);
return rc;
}
struct http *
http_create() {
struct http *h;
h = zmalloc(sizeof(struct http));
h->write_function = null_write_data;
h->header_write_function = null_write_data;
return h;
}
void
http_free(struct http *h) {
curl_easy_cleanup(h->ch);
free(h);
}
long
http_perform(struct http *h) {
long response_code;
struct curl_slist *header_list = NULL;
if (h->response_body && (h->write_function == NULL || h->write_function == null_write_data))
h->write_function = default_write_data;
if (h->response_header && (h->header_write_function == NULL || h->header_write_function == null_write_data))
h->header_write_function = default_write_data;
h->curl_status = CURLE_OK;
if ((h->ch = curl_easy_init()) == NULL) {
return -1;
}
curl_easy_setopt(h->ch, CURLOPT_URL, h->url);
curl_easy_setopt(h->ch, CURLOPT_CUSTOMREQUEST, h->method);
curl_easy_setopt(h->ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_easy_setopt(h->ch, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(h->ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_easy_setopt(h->ch, CURLOPT_WRITEFUNCTION, h->write_function);
curl_easy_setopt(h->ch, CURLOPT_WRITEDATA, h->response_body);
curl_easy_setopt(h->ch, CURLOPT_HEADERFUNCTION, h->header_write_function);
curl_easy_setopt(h->ch, CURLOPT_HEADERDATA, h->response_header);
curl_easy_setopt(h->ch, CURLOPT_ERRORBUFFER, h->error);
curl_easy_setopt(h->ch, CURLOPT_NOSIGNAL, 1);
if (h->body) {
curl_easy_setopt(h->ch, CURLOPT_POSTFIELDS, (const char *) h->body);
curl_easy_setopt(h->ch, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)h->body_length);
}
if (h->headers) {
while (*(h->headers)) {
header_list = curl_slist_append(header_list, *h->headers++);
}
curl_easy_setopt(h->ch, CURLOPT_HTTPHEADER, header_list);
}
if (h->extra_config_function && h->extra_config_function(h->ch, h->extra_config_data) != 0) {
response_code = -1;
goto out;
}
if ((h->curl_status = curl_easy_perform(h->ch)) != CURLE_OK) {
response_code = -1;
goto out;
}
curl_easy_getinfo(h->ch, CURLINFO_RESPONSE_CODE, &response_code);
out:
curl_slist_free_all(header_list);
return response_code;
}
已解决:
根据theamk的回答,我设法直接通过base64解决了这个问题,然后将文件传递给我拥有的模板引擎,它起作用了,当HTTP响应代码为200时,文件成功返回,只需printf转义它。
long rc;
struct buf_string response = {0};
rc = http_get(url, &response, (const char *[]){"Accept: */*", "Accept-Encoding: gzip, deflate", "User-Agent: micro-service/0.1", NULL});
/* If the file is not found, abort */
if (rc != 200) {
cs->error = "ATTACHMENT_FILE_NOT_FOUND";
continue;
}
/* Convert the file payload to Base64, then pass it to the email params */
int len = response.pos;
size_t sz = BASE64_NEEDED(len);
char *b64 = zmalloc(sz);
base64_encode(b64, response.buf, len);
template_parse("send_reply.tmpl", "attachment_data", b64);
free(b64);
您正在正确获取文件,您根本无法将 PDF 和 JPEG 打印到屏幕上——您会得到如您所见的随机字符。
具体来说,您的 4 字符示例似乎来自 JPEG 文件——其中许多以 ff:d8:ff:e0:00 字符开头,将打印为下面的字符串(四个无效字符,然后是 'printf' 将停止打印,因为它会遇到代码为 0)
的字符
为确保您正确下载文件,请将数据保存到文件,然后使用 JPEG/PDF 查看器打开文件。确保在写入数据时使用 fwrite()(printf() 或 fputs() 将无法工作,因为嵌入了二进制零)
我正在尝试使用 CURL Lib 通过 C 包装器从我的 Amazon S3 获取图像和 PDF 文件,目前我可以获得类似 txt 文件、类似错误的 HTTP HTML 响应,但是当我尝试获取我收到的 PDF 和 JPEG 文件作为响应:
(DEBUG) Size : 90343
(DEBUG) Response : ����
我不知道这些奇怪的字符是从哪里来的,但我怀疑我需要添加CURLOPT_BINARYTRANSFER
下面是使用 CURL 的 HTTP GET 函数和定义:
const char *url = "http://bucket.s3.amazonaws.com/file.pdf";
long rc;
struct buf_string response = {0};
rc = http_get(url, &response, (const char *[]){"Accept: */*", "Accept-Encoding: gzip, deflate", "User-Agent: web-service/0.1", NULL});
if (rc != 200) { /* error */ }
logprintf(ts, D_DEBUG, "Size : %d", response.pos);
logprintf(ts, D_ERROR, "Response : %s", response.buf);
long
http_get(const char *url, struct buf_string *response, const char *headers[]) {
struct http *h = http_create();
long rc;
h->method = "GET";
h->url = url;
h->headers = headers;
if (response) {
memset(response, 0, sizeof(*response));
h->response_body = response;
h->write_function = default_write_data;
}
rc = http_perform(h);
http_free(h);
return rc;
}
struct http *
http_create() {
struct http *h;
h = zmalloc(sizeof(struct http));
h->write_function = null_write_data;
h->header_write_function = null_write_data;
return h;
}
void
http_free(struct http *h) {
curl_easy_cleanup(h->ch);
free(h);
}
long
http_perform(struct http *h) {
long response_code;
struct curl_slist *header_list = NULL;
if (h->response_body && (h->write_function == NULL || h->write_function == null_write_data))
h->write_function = default_write_data;
if (h->response_header && (h->header_write_function == NULL || h->header_write_function == null_write_data))
h->header_write_function = default_write_data;
h->curl_status = CURLE_OK;
if ((h->ch = curl_easy_init()) == NULL) {
return -1;
}
curl_easy_setopt(h->ch, CURLOPT_URL, h->url);
curl_easy_setopt(h->ch, CURLOPT_CUSTOMREQUEST, h->method);
curl_easy_setopt(h->ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_easy_setopt(h->ch, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(h->ch, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_easy_setopt(h->ch, CURLOPT_WRITEFUNCTION, h->write_function);
curl_easy_setopt(h->ch, CURLOPT_WRITEDATA, h->response_body);
curl_easy_setopt(h->ch, CURLOPT_HEADERFUNCTION, h->header_write_function);
curl_easy_setopt(h->ch, CURLOPT_HEADERDATA, h->response_header);
curl_easy_setopt(h->ch, CURLOPT_ERRORBUFFER, h->error);
curl_easy_setopt(h->ch, CURLOPT_NOSIGNAL, 1);
if (h->body) {
curl_easy_setopt(h->ch, CURLOPT_POSTFIELDS, (const char *) h->body);
curl_easy_setopt(h->ch, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)h->body_length);
}
if (h->headers) {
while (*(h->headers)) {
header_list = curl_slist_append(header_list, *h->headers++);
}
curl_easy_setopt(h->ch, CURLOPT_HTTPHEADER, header_list);
}
if (h->extra_config_function && h->extra_config_function(h->ch, h->extra_config_data) != 0) {
response_code = -1;
goto out;
}
if ((h->curl_status = curl_easy_perform(h->ch)) != CURLE_OK) {
response_code = -1;
goto out;
}
curl_easy_getinfo(h->ch, CURLINFO_RESPONSE_CODE, &response_code);
out:
curl_slist_free_all(header_list);
return response_code;
}
已解决: 根据theamk的回答,我设法直接通过base64解决了这个问题,然后将文件传递给我拥有的模板引擎,它起作用了,当HTTP响应代码为200时,文件成功返回,只需printf转义它。
long rc;
struct buf_string response = {0};
rc = http_get(url, &response, (const char *[]){"Accept: */*", "Accept-Encoding: gzip, deflate", "User-Agent: micro-service/0.1", NULL});
/* If the file is not found, abort */
if (rc != 200) {
cs->error = "ATTACHMENT_FILE_NOT_FOUND";
continue;
}
/* Convert the file payload to Base64, then pass it to the email params */
int len = response.pos;
size_t sz = BASE64_NEEDED(len);
char *b64 = zmalloc(sz);
base64_encode(b64, response.buf, len);
template_parse("send_reply.tmpl", "attachment_data", b64);
free(b64);
您正在正确获取文件,您根本无法将 PDF 和 JPEG 打印到屏幕上——您会得到如您所见的随机字符。
具体来说,您的 4 字符示例似乎来自 JPEG 文件——其中许多以 ff:d8:ff:e0:00 字符开头,将打印为下面的字符串(四个无效字符,然后是 'printf' 将停止打印,因为它会遇到代码为 0)
的字符为确保您正确下载文件,请将数据保存到文件,然后使用 JPEG/PDF 查看器打开文件。确保在写入数据时使用 fwrite()(printf() 或 fputs() 将无法工作,因为嵌入了二进制零)