LinuxC语言实现上传功能(curl)
来源:互联网 发布:mysql最大连接数 编辑:程序博客网 时间:2024/06/04 18:55
该程序是对接阿里云时做得,上传其他平台可能会略有差异,请注意!
直接上代码(注意参数,最好能看懂上传的大致流程,其实也是用curl):
#include <stdio.h>#include <string.h>#include <time.h>#include <fcntl.h>#include <sys/stat.h>#include "curl.h"#include "util.h"static char AccessKeyIdG[64] = {0};static char SecretAccessKeyG[64] = {0};static char Server_addr[64] = {0};static char Bucket[64] = {0};#define CONFIGINI"/mnt/mtd/SystemConfig.ini"time_t start_time,end_time;#define S3_METADATA_HEADER_NAME_PREFIX "x-amz-meta-"#define S3_MAX_METADATA_COUNT \ (2048 / (sizeof(S3_METADATA_HEADER_NAME_PREFIX "nv") - 1))#define COMPACTED_METADATA_BUFFER_SIZE \(2048 * sizeof(S3_METADATA_HEADER_NAME_PREFIX "n: v"))// Declare a string multibuffer with the given name of the given maximum size#define string_multibuffer(name, size) \ char name[size]; \ int name##Sizetypedef struct _RequestComputedValues{ char host[80]; char uri[128]; int fileLen; // 要传输文件的长度 // All x-amz- headers, in normalized form (i.e. NAME: VALUE, no other ws) char *amzHeaders[S3_MAX_METADATA_COUNT + 2]; // + 2 for acl and date // The number of x-amz- headers int amzHeadersCount; // Storage for amzHeaders (the +256 is for x-amz-acl and x-amz-date) char amzHeadersRaw[COMPACTED_METADATA_BUFFER_SIZE + 256 + 1]; // URL-Encoded key char urlEncodedKey[60]; string_multibuffer(canonicalizedAmzHeaders, COMPACTED_METADATA_BUFFER_SIZE + 256 + 1); // Canonicalized resource char canonicalizedResource[128]; // Content-Type header (or empty) char contentTypeHeader[2]; // Content-MD5 header (or empty) char md5Header[2]; // Authorization header char authorizationHeader[128];} RequestComputedValues;int Config_Read_String_Params(const char* lpSessionName,const char* lpKeyName,char* lpOutBuff){ int value; intret; charszStr[300]; ret = GetProfileString(CONFIGINI,lpSessionName,lpKeyName,szStr,300); if(ret == -1) { ret = GetProfileInteger(CONFIGINI,lpSessionName,lpKeyName,&value); if(ret == -1) { printf("Load [%s] config [%s] error\n",lpSessionName,lpKeyName); return -1; } else { sprintf(lpOutBuff,"%d",value); printf("Load [%s][%s] = [%s]\n",lpSessionName,lpKeyName,lpOutBuff); } } else { sprintf(lpOutBuff,"%s",szStr); printf("Load [%s][%s] = [%s]\n",lpSessionName,lpKeyName,lpOutBuff); } return 0;}int checkout_server_addr(){ int ret = 0; Config_Read_String_Params("Tutk","AccessKeyIdG",AccessKeyIdG); if(strlen(AccessKeyIdG) == 0) { printf("AccessKeyIdG : NULL \n"); return 0; } else { printf("AccessKeyIdG :%s\n",AccessKeyIdG); } Config_Read_String_Params("Tutk","SecretAccessKeyG",SecretAccessKeyG); if(strlen(SecretAccessKeyG) == 0) { printf("SecretAccessKeyG : NULL \n"); return 0; } else { printf("SecretAccessKeyG :%s\n",SecretAccessKeyG); } Config_Read_String_Params("Tutk","Server_addr",Server_addr); if(strlen(Server_addr) == 0) { printf("Server_addr : NULL \n"); return 0; } else { printf("Server_addr :%s\n",Server_addr); } Config_Read_String_Params("Tutk","Bucket",Bucket); if(strlen(Bucket) == 0) { printf("Bucket : NULL \n"); return 0; } else { printf("Bucket :%s\n",Bucket); } return 1;}static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp){ printf("[%s:%d] size[%d] nmemb[%d]\n", __FUNCTION__, __LINE__, size, nmemb); FILE *fp = (FILE *)userp; if(!fp) { printf("[%s:%d] file point fp NULL\n", __FUNCTION__, __LINE__); } if(size*nmemb < 1) { printf("read_callback error, size[%d] nmemb[%d]\n", size, nmemb); return 0; } end_time = time(NULL); if((end_time - start_time) > 120) { printf("sending overtime:%d close file...\n", end_time - start_time); close(fp); return 0; } else { printf("sending...:%ld\n", end_time); size_t retcode = fread(ptr, size, nmemb, fp); printf("read_callback fread retcode:%d\n", retcode); return retcode; }}int init_amz_header(RequestComputedValues *values){ int len = 0; // Append a header to amzHeaders, trimming whitespace from the end. // Does NOT trim whitespace from the beginning.#define headers_append(isNewHeader, format, ...) \do { \ if (isNewHeader) { \ values->amzHeaders[values->amzHeadersCount++] = \ &(values->amzHeadersRaw[len]); \ } \ len += snprintf(&(values->amzHeadersRaw[len]), \ sizeof(values->amzHeadersRaw) - len, \ format, __VA_ARGS__); \ if (len >= (int) sizeof(values->amzHeadersRaw)) { \ return -1; \ } \ while ((len > 0) && (values->amzHeadersRaw[len - 1] == ' ')) { \ len--; \ } \ values->amzHeadersRaw[len++] = 0; \} while (0) //headers_append(1, "x-amz-server-side-encryption: %s", "AES256"); // Add the x-amz-date header time_t now = time(NULL); char date[64]; struct tm *gmt; gmt = gmtime(&now); strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S GMT", gmt); headers_append(1, "Date: %s", date);}#define MAX_MSG_LEN 1024static int aws_authorizationHeader(RequestComputedValues *values){ printf("[%s][%s][%d]: \n",__FILE__,__FUNCTION__,__LINE__); // We allow for: // 17 bytes for HTTP-Verb + \n // 129 bytes for Content-MD5 + \n // 129 bytes for Content-Type + \n // 1 byte for empty Date + \n // CanonicalizedAmzHeaders & CanonicalizedResource char signbuf[17 + 129 + 129 + 1 + (sizeof(values->canonicalizedAmzHeaders) - 1) + (sizeof(values->canonicalizedResource) - 1) + 1] = {0}; int len = 0;#define signbuf_append(format, ...) \ len += snprintf(&(signbuf[len]), sizeof(signbuf) - len, \ format, __VA_ARGS__) signbuf_append("%s\n", "PUT"); // For MD5 and Content-Type, use the value in the actual header, because // it's already been trimmed signbuf_append("%s\n", values->md5Header[0] ? &(values->md5Header[sizeof("Content-MD5: ") - 1]) : ""); /* signbuf_append("%s\n", "video/avi"); sprintf(values->contentTypeHeader, "Content-Type: %s", "video/avi"); */ signbuf_append ("%s\n", values->contentTypeHeader[0] ? &(values->contentTypeHeader[sizeof("Content-Type:") - 1]) : ""); //signbuf_append("%s", values->canonicalizedAmzHeaders); char date[128] = {0}; //sprintf(values->canonicalizedAmzHeaders, "Date: %s", date); memcpy(date, &values->canonicalizedAmzHeaders[sizeof("Date:")-1], sizeof(date)); signbuf_append("%s", date); signbuf_append("%s", values->canonicalizedResource); // Generate an HMAC-SHA-1 of the signbuf unsigned char hmac[20]; OSS_HMAC_SHA1(hmac, (unsigned char *) SecretAccessKeyG, strlen(SecretAccessKeyG), (unsigned char *) signbuf, len); //DPRINT("HMAC_SHA1 hmac:[%s]\n", hmac); // Now base-64 encode the results char b64[((20 + 1) * 4) / 3]; int b64Len = oss_base64Encode(hmac, 20, b64); //DPRINT("base64Encode hmac:[%s] b64[%s]\n", hmac, b64); snprintf(values->authorizationHeader, sizeof(values->authorizationHeader), "Authorization: OSS %s:%.*s", AccessKeyIdG, b64Len, b64); printf("authorizationHeader:[%s]\n", values->authorizationHeader); printf("signbuf:{\n%s\n}\n", signbuf); return 1;}// Compose the URI to use for the request given the request parametersstatic int compose_uri(char *buffer, int bufferSize, const char *urlEncodedKey){ int len = 0;#define uri_append(fmt, ...) \ do { \ len += snprintf(&(buffer[len]), bufferSize - len, fmt, __VA_ARGS__); \ if (len >= bufferSize) { \ return -1; \ } \ } while (0) //uri_append("http%s://", (bucketContext->protocol == S3ProtocolHTTP) ? "" : "s"); uri_append("http%s://", ""); uri_append("%s.%s", Bucket, Server_addr); uri_append("%s", "/"); uri_append("%s", urlEncodedKey); return 1;}// Simple comparison function for comparing two HTTP header names that are// embedded within an HTTP header line, returning true if header1 comes// before header2 alphabetically, false if notstatic int headerle(const char *header1, const char *header2){ while (1) { if (*header1 == ':') { return (*header2 != ':'); } else if (*header2 == ':') { return 0; } else if (*header2 < *header1) { return 0; } else if (*header2 > *header1) { return 1; } header1++, header2++; }}// Replace this with merge sort eventually, it's the best stable sort. But// since typically the number of elements being sorted is small, it doesn't// matter that much which sort is used, and gnome sort is the world's simplest// stable sort. Added a slight twist to the standard gnome_sort - don't go// forward +1, go forward to the last highest index considered. This saves// all the string comparisons that would be done "going forward", and thus// only does the necessary string comparisons to move values back into their// sorted position.static void header_gnome_sort(const char **headers, int size){ int i = 0, last_highest = 0; while (i < size) { if ((i == 0) || headerle(headers[i - 1], headers[i])) { i = ++last_highest; } else { const char *tmp = headers[i]; headers[i] = headers[i - 1]; headers[--i] = tmp; } }}static void canonicalize_amz_headers(RequestComputedValues *values){ // Make a copy of the headers that will be sorted const char *sortedHeaders[S3_MAX_METADATA_COUNT]; memcpy(sortedHeaders, values->amzHeaders, (values->amzHeadersCount * sizeof(sortedHeaders[0]))); // Now sort these header_gnome_sort(sortedHeaders, values->amzHeadersCount); // Now copy this sorted list into the buffer, all the while: // - folding repeated headers into single lines, and // - folding multiple lines // - removing the space after the colon int lastHeaderLen = 0, i; char *buffer = values->canonicalizedAmzHeaders; for (i = 0; i < values->amzHeadersCount; i++) { const char *header = sortedHeaders[i]; const char *c = header; // If the header names are the same, append the next value if ((i > 0) && !strncmp(header, sortedHeaders[i - 1], lastHeaderLen)) { // Replacing the previous newline with a comma *(buffer - 1) = ','; // Skip the header name and space c += (lastHeaderLen + 1); } // Else this is a new header else { // Copy in everything up to the space in the ": " while (*c != ' ') { *buffer++ = *c++; } // Save the header len since it's a new header lastHeaderLen = c - header; // Skip the space c++; } // Now copy in the value, folding the lines while (*c) { // If c points to a \r\n[whitespace] sequence, then fold // this newline out if ((*c == '\r') && (*(c + 1) == '\n') && is_blank(*(c + 2))) { c += 3; while (is_blank(*c)) { c++; } // Also, what has most recently been copied into buffer amy // have been whitespace, and since we're folding whitespace // out around this newline sequence, back buffer up over // any whitespace it contains while (is_blank(*(buffer - 1))) { buffer--; } continue; } *buffer++ = *c++; } // Finally, add the newline *buffer++ = '\n'; } // Terminate the buffer *buffer = 0;}void init_header(RequestComputedValues *values, char *filename, int filesize){ if(!filename) { printf("filename NULL, error\n"); return ; } //memset(&rq_computed, 0, sizeof(rq_computed)); values->fileLen = filesize; init_amz_header(values); //set Url snprintf(values->host, sizeof(values->host), "%s.%s", Bucket, Server_addr); printf("init_header values->host[%s]\n", values->host); //filename snprintf(values->urlEncodedKey, sizeof(values->urlEncodedKey), "%s", filename); printf("init_header values->urlEncodedKey[%s]\n", values->urlEncodedKey); canonicalize_amz_headers(values); printf("canonicalize_amz_headers:[%s]\n", values->canonicalizedAmzHeaders); //设置上传虚拟地址 snprintf(values->canonicalizedResource, sizeof(values->canonicalizedResource), "/%s/%s", Bucket, values->urlEncodedKey); aws_authorizationHeader(values); compose_uri(values->uri, sizeof(values->uri), values->urlEncodedKey);}int setup_url(RequestComputedValues *values, CURL *curl){ printf("[%s][%s][%d]: \n",__FILE__,__FUNCTION__,__LINE__); int status;#define curl_easy_setopt_safe(opt, val) \if ((status = curl_easy_setopt\ (curl, opt, val)) != CURLE_OK) {\return status;\} // Ask curl to parse the Last-Modified header. This is easier than // parsing it ourselves. printf("[%s][%s][%d]: \n",__FILE__,__FUNCTION__,__LINE__); struct curl_slist *headers_slist = 0; // Append standard headers#define append_standard_header(fieldName) \ if (values-> fieldName [0]) { \ headers_slist = curl_slist_append(headers_slist, \ values-> fieldName); \ } append_standard_header(contentTypeHeader); append_standard_header(md5Header); // Append x-amz- headers int i; for (i = 0; i < values->amzHeadersCount; i++) { printf("values->amzHeaders[%d]:%s\n", i, values->amzHeaders[i]); headers_slist = curl_slist_append(headers_slist, values->amzHeaders[i]); } append_standard_header(authorizationHeader); { char header[256]; snprintf(header, sizeof(header), "Content-Length: %llu", (unsigned long long) values->fileLen); headers_slist = curl_slist_append(headers_slist, header); headers_slist = curl_slist_append(headers_slist, "Transfer-Encoding:"); headers_slist = curl_slist_append(headers_slist, "Expect:"); } // Set the HTTP headers curl_easy_setopt_safe(CURLOPT_HTTPHEADER, headers_slist); curl_easy_setopt_safe(CURLOPT_URL, values->uri); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120);//设置超时时间 // Set request type. curl_easy_setopt_safe(CURLOPT_UPLOAD, 1); printf("[%s][%s][%d]: \n",__FILE__,__FUNCTION__,__LINE__); return 1;}int _upload(char *avi_filename,char *upload_path){ CURL *curl; CURLcode res; struct stat file_info; char filename[60] = {0}; FILE *out = NULL; printf("----------avi_filename: %s\n",avi_filename); printf("----------upload_path: %s\n",upload_path); if(!checkout_server_addr()) { printf("checkout_server_addr failed!\n"); return -1; } printf("checkout_server_addr successfully!\n"); if(avi_filename != NULL) { strcpy(filename, avi_filename); out = fopen(filename, "rb"); if(!out) { printf("fopen filename %s failed\n", filename); return -1; } } else { printf("avi_filename is NULL!\n"); return -1; } stat(filename, &file_info); int uploadsize = file_info.st_size; /* In windows, this will init the winsock stuff */ res = curl_global_init(CURL_GLOBAL_DEFAULT); /* Check for errors */ if(res != CURLE_OK) { fprintf(stderr, "curl_global_init() failed: %s\n", curl_easy_strerror(res)); fclose(out); return -1; } RequestComputedValues rq_computed; memset(&rq_computed, 0, sizeof(rq_computed)); char object_name[128] = {0}; //strcpy(object_name, upload_path); sprintf(object_name, "%s", upload_path); printf("----------object_name: %s\n",object_name); printf("----------uploadsize: %d\n",uploadsize); init_header(&rq_computed, object_name, uploadsize); /* get a curl handle */ curl = curl_easy_init(); if(curl) { printf("url:%s\n", rq_computed.uri); /* First set the URL that is about to receive our POST. */ //curl_easy_setopt(curl, CURLOPT_URL, url); setup_url(&rq_computed, curl);#if 0 /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* HTTP PUT please */ curl_easy_setopt(curl, CURLOPT_PUT, 1L);#endif /* we want to use our own read function */ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); /* pointer to pass to our read function */ curl_easy_setopt(curl, CURLOPT_READDATA, out); /* get verbose debug output please */ //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the request, res will get the return code */ start_time = time(NULL); printf("start_time:%ld\n", start_time); res = curl_easy_perform(curl); /* Check for errors */ if(res != CURLE_OK) //传输失败 { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); fclose(out); curl_easy_cleanup(curl); curl_global_cleanup(); return -1; } /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); printf("send finish at time:%ld\n", time(NULL)); fclose(out); return 0;}
阅读全文
1 0
- LinuxC语言实现上传功能(curl)
- LinuxC语言实现下载功能(curl)
- c/c++/curl实现facebook上传图片等功能
- LinuxC语言实现递归删除目录
- curl 实现sftp功能
- php curl 实现文件上传
- LinuxC语言笔记
- linuxC语言数组基础知识
- php 远程上传(CURL)
- 原 QNetworkAccessManager实现curl上传表单文件
- LinuxC编程一站式学习(C语言本质)
- 用LinuxC实现pstree
- 批量上传文件(功能实现)
- js实现复制功能(文件上传)
- Felx上传功能实现
- Flex上传功能实现
- 上传预览功能实现
- nodejs上传功能实现
- 微信小程序开发,提示“不在以下合法域名列表中,请参考文档”
- Determining What Serial Ports Are Available on a Windows Machine
- 基于微信公众平台的二维码签到系统-----(2)二维码的生成以及内网穿透ngrok代理服务器的使用
- 语音听写与合成--(讯飞语音识别与合成&&百度语音识别)
- CodeVS2490 导弹防御塔 【二分答案】【匈牙利】
- LinuxC语言实现上传功能(curl)
- 上传头像
- Oracle 增加修改删除字段
- TCP粘包问题
- PCA原理详解
- Javadoc注释的用法
- JavaSE大纲以及学习网址
- 简单的图论问题?
- sql获取日期区间(年、月、周、日)