iOS用libcurl發起一個get請求,並儲存返回資料到沙盒

Auditore發表於2018-01-03

這個需求分為: 1.如何接入libcurl庫, 2.如何用libcurl發起get請求, 3.如何將資料儲存到沙盒路徑下

一.第一個需求,由於libcurl只有原始碼,需要你自己去編譯各平臺下的庫,怎麼編譯參考下我寫的另一篇文章:編譯支援iOS的libcurl+OpenSSL庫(支援https IPv6)
然後就是引用libcurl.a庫了,記得在build phase裡面的link binary with ibraries 裡面引用libz.tbdlibresolv.tbd這兩個系統庫

二.第二個需求,發起請求的方法如下

bool getUrl(const char *filename,char *url)
{
    CURL *curl;
    CURLcode res;
    FILE *fp;
    if ((fp = fopen(filename, "wt+")) == NULL){
        // 返回結果用檔案儲存
        return false;
    }
    struct curl_slist *headers = NULL;
    //增加HTTP header
    headers = curl_slist_append(headers, "Accept:application/json");
    headers = curl_slist_append(headers, "Content-Type:application/json");
    headers = curl_slist_append(headers, "charset:utf-8");
    curl = curl_easy_init();    // 初始化
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改協議頭
        curl_easy_setopt(curl, CURLOPT_URL,url);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);   // 執行
        NSLog(@"請求返回值是%i",res);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    fclose(fp);
    return true;
}
複製程式碼

特別提醒, curl_global_init(CURL_GLOBAL_ALL);這個函式是全域性初始化函式,只能呼叫一次,所以最好在didFinishLanuch裡面呼叫,如果在curl_easy_init();之前還未實現,那麼libcurl會自動執行一次。所以多執行緒下最好主動呼叫該函式以防止線上程中curl_easy_init時多次呼叫。 這是因為雖然libcurl是執行緒安全的,但curl_global_init是不能保證執行緒安全的,所以不要在每個執行緒中都呼叫curl_global_init,didFinishLanuch裡呼叫一次就行了。

三. 如何上層呼叫 由於curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); 這個方法是c的方法,所以傳進來的目錄filename也要是c String才行,所以上層呼叫的時候得這麼寫:

NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths firstObject];
NSString *filePath = [documentPath stringByAppendingPathComponent:@"wow.log"];
getUrl([filePath cStringUsingEncoding:NSUTF8StringEncoding],"https://www.baidu.com");
複製程式碼

這樣就可以將獲取到資料寫入到應用的document目錄下,儲存為wow.log檔案。

四. 對請求的返回值的說明 也就是對 curl_easy_perform()函式返回值的說明,0表示請求正常返回,詳情看下面

CURLE_OK = 0, 0: no error 
CURLE_UNSUPPORTED_PROTOCOL, 1: unsupported protocol 
CURLE_FAILED_INIT, 2: failed init 
CURLE_URL_MALFORMAT, 3: URL using bad/illegal format or missing URL 
CURLE_URL_MALFORMAT_USER, 4: unknown error 
CURLE_COULDNT_RESOLVE_PROXY, 5: couldn't resolve proxy name 
CURLE_COULDNT_RESOLVE_HOST, 6: couldn't resolve host name 
CURLE_COULDNT_CONNECT, 7: couldn't connect to server 
CURLE_FTP_WEIRD_SERVER_REPLY, 8: FTP: weird server reply 
CURLE_FTP_ACCESS_DENIED, 
CURLE_FTP_USER_PASSWORD_INCORRECT, 10: unknown error 
CURLE_FTP_WEIRD_PASS_REPLY, 11: FTP: unknown PASS reply 
CURLE_FTP_WEIRD_USER_REPLY, 12: FTP: unknown USER reply 
CURLE_FTP_WEIRD_PASV_REPLY, 13: FTP: unknown PASV reply 
CURLE_FTP_WEIRD_227_FORMAT, 14: FTP: unknown 227 response format 
CURLE_FTP_CANT_GET_HOST, 15: FTP: can't figure out the host in the PASV response 
CURLE_FTP_CANT_RECONNECT, 16: FTP: can't connect to server the response code is unknown 
CURLE_FTP_COULDNT_SET_BINARY, 17: FTP: couldn't set binary mode 
CURLE_PARTIAL_FILE, 18: Transferred a partial file 
CURLE_FTP_COULDNT_RETR_FILE, 19: FTP: couldn't retrieve (RETR failed) the specified file 
CURLE_FTP_WRITE_ERROR, 20: FTP: the post-transfer acknowledge response was not OK 
CURLE_FTP_QUOTE_ERROR, 21: FTP: a quote command returned error 
CURLE_HTTP_RETURNED_ERROR, 22: HTTP response code said error 
CURLE_WRITE_ERROR, 23: failed writing received data to disk/application 
CURLE_MALFORMAT_USER, 24: unknown error 
CURLE_UPLOAD_FAILED, 25: upload failed (at start/before it took off) 
CURLE_READ_ERROR, 26: failed to open/read local data from file/application 
CURLE_OUT_OF_MEMORY, 27: out of memory 

CURLE_OPERATION_TIMEOUTED, 28: a timeout was reached 
CURLE_FTP_COULDNT_SET_ASCII, 29: FTP could not set ASCII mode (TYPE A) 
CURLE_FTP_PORT_FAILED, 30: FTP command PORT failed 
CURLE_FTP_COULDNT_USE_REST, 31: FTP command REST failed 
CURLE_FTP_COULDNT_GET_SIZE, 32: FTP command SIZE failed 
CURLE_HTTP_RANGE_ERROR, 33: a range was requested but the server did not deliver it 
CURLE_HTTP_POST_ERROR, 34: internal problem setting up the POST 
CURLE_SSL_CONNECT_ERROR, 35: SSL connect error 
CURLE_BAD_DOWNLOAD_RESUME, 36: couldn't resume download 
CURLE_FILE_COULDNT_READ_FILE, 37: couldn't read a file:// file 
CURLE_LDAP_CANNOT_BIND, 38: LDAP: cannot bind 
CURLE_LDAP_SEARCH_FAILED, 39: LDAP: search failed 
CURLE_LIBRARY_NOT_FOUND, 40: a required shared library was not found
複製程式碼

五. 單純地寫一個請求 如果你不需要寫入本地,只是想發起請求,當然也是可以的,簡化上面的程式碼,結果如下

CURLcode getUrl(char *url)
{
    CURL *curl;
    CURLcode res = CURLE_OK;
    struct curl_slist *headers = NULL;
    //增加HTTP header
    headers = curl_slist_append(headers, "Accept:application/json");
    headers = curl_slist_append(headers, "Content-Type:application/json");
    headers = curl_slist_append(headers, "charset:utf-8");
    curl = curl_easy_init();    // 初始化
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);// 改協議頭
        curl_easy_setopt(curl, CURLOPT_URL,url);
        res = curl_easy_perform(curl);   // 執行
        NSLog(@"res===%i",res);
        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    return res;
}
複製程式碼

呼叫的話就用getUrl("https://www.baidu.com");
打完收工

相關文章