C 使用 CURL 获取文件

标签 c http curl libcurl

我正在尝试使用 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() 将无法工作,因为嵌入了二进制零)

关于C 使用 CURL 获取文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32361276/

相关文章:

java - 在 Android 中从 HTTP 检索 XML/流的最佳实践

PHP curl,特殊网络接口(interface)

c - fwrite 在每个输入后添加新行

c - 当tcp使用16位端口号识别应用程序时,怎么会存在非独占端口呢?

C无法使用变量打开文件

C 方法应该调用自己递归两次,但似乎没有这样做

http - HTTP 中的 POST 和 PUT 有什么区别?

http - HLS 和 MPEG-DASH 是否存在于 HTTP 消息正文中?

java - 通过curl 的Elasticsearch REST api 无法从java.runtime.exec 运行

php - 使用 PHP curl 出现 411 错误