HTTP Client data container for form(multipart/form-data)
Dependencies: mbed EthernetInterface HTTPClient mbed-rtos
HTTPPoster.cpp
00001 /* HTTPPoster.cpp */ 00002 00003 //Debug is disabled by default 00004 #if 1 00005 //Enable debug 00006 #include <cstdio> 00007 #define DBG(x, ...) std::printf("[HTTPPoster : DBG]"x"\r\n", ##__VA_ARGS__); 00008 //#define DBG(x, ...) 00009 #define WARN(x, ...) std::printf("[HTTPPoster : WARN]"x"\r\n", ##__VA_ARGS__); 00010 #define ERR(x, ...) std::printf("[HTTPPoster : ERR]"x"\r\n", ##__VA_ARGS__); 00011 00012 #else 00013 //Disable debug 00014 #define DBG(x, ...) 00015 #define WARN(x, ...) 00016 #define ERR(x, ...) 00017 00018 #endif 00019 00020 #include "HTTPPoster.h" 00021 00022 #define OK 0 00023 00024 ///HTTP Client data container for form(multipart/form-data) 00025 HTTPPoster::HTTPPoster() 00026 { 00027 m_cur = 0; 00028 m_seq = 0; 00029 m_send_len = 0; 00030 m_fp = NULL; 00031 m_post_data.clear(); 00032 m_buf.clear(); 00033 m_boundary = "----HTTPPoster123"; 00034 m_ContentType = "multipart/form-data; boundary="; 00035 m_ContentType += m_boundary; 00036 } 00037 00038 HTTPPoster::~HTTPPoster() 00039 { 00040 if (m_fp) { 00041 fclose(m_fp); 00042 m_fp = NULL; 00043 } 00044 } 00045 00046 bool HTTPPoster::addFile(const char* name, const char* path) 00047 { 00048 struct stpost data; 00049 00050 m_fp = fopen(path, "rb"); 00051 if (m_fp == NULL) { 00052 return false; 00053 } 00054 fseek(m_fp, 0, SEEK_END); 00055 data.length = ftell(m_fp); 00056 fclose(m_fp); 00057 00058 string head = "Content-Disposition: form-data; name=\""; 00059 head += name; 00060 head += "\"; filename=\""; 00061 head += path; 00062 head += "\""; 00063 00064 data.head = head; 00065 data.value = path; 00066 data.file = true; 00067 m_post_data.push_back(data); 00068 return true; 00069 } 00070 00071 bool HTTPPoster::add(const char* name, const char* value) 00072 { 00073 struct stpost data; 00074 00075 string head = "Content-Disposition: form-data; name=\""; 00076 head += name; 00077 head += "\""; 00078 00079 data.head = head; 00080 data.value = value; 00081 data.length = strlen(value); 00082 data.file = false; 00083 m_post_data.push_back(data); 00084 return true; 00085 } 00086 00087 /*virtual*/ int HTTPPoster::read(char* buf, size_t len, size_t* pReadLen) 00088 { 00089 int c; 00090 switch(m_seq) { 00091 case 0: 00092 if (m_cur >= m_post_data.size()) { 00093 m_buf += "--"; 00094 m_buf += m_boundary; 00095 m_buf += "--\r\n"; 00096 m_seq = 4; // done 00097 } else { 00098 m_buf += "--"; 00099 m_buf += m_boundary; 00100 m_buf += "\r\n"; 00101 m_seq++; 00102 } 00103 break; 00104 case 1: 00105 m_buf += m_post_data[m_cur].head; 00106 m_buf += "\r\n\r\n"; 00107 if (m_post_data[m_cur].file) { 00108 m_fp = fopen(m_post_data[m_cur].value.c_str(), "rb"); 00109 } 00110 m_pos = 0; 00111 m_seq++; 00112 break; 00113 case 2: 00114 for(int i = 0; i < len; i++) { 00115 if (m_buf.size() >= len) { 00116 break; 00117 } 00118 if (m_pos >= m_post_data[m_cur].length) { 00119 m_seq++; 00120 break; 00121 } 00122 if (m_post_data[m_cur].file) { 00123 c = fgetc(m_fp); 00124 } else { 00125 c = m_post_data[m_cur].value[m_pos]; 00126 } 00127 m_buf += (char)c; 00128 m_pos++; 00129 } 00130 break; 00131 case 3: 00132 m_buf += "\r\n"; 00133 if (m_fp) { 00134 fclose(m_fp); 00135 m_fp = NULL; 00136 } 00137 m_cur++; 00138 m_seq = 0; 00139 break; 00140 default: // done 00141 break; 00142 } 00143 int len2 = m_buf.size(); 00144 if (len2 > len) { 00145 len2 = len; 00146 } 00147 memcpy(buf, m_buf.data(), len2); 00148 m_buf.erase(0, len2); 00149 m_send_len += len2; 00150 DBG("m_len=%d m_send_len=%d len=%d len2=%d", m_len, m_send_len, len, len2); 00151 *pReadLen = len2; 00152 return OK; 00153 } 00154 00155 /*virtual*/ int HTTPPoster::getDataType(char* type, size_t maxTypeLen) //Internet media type for Content-Type header 00156 { 00157 if (m_ContentType.length() >= maxTypeLen) { 00158 WARN("maxTypeLen=%d", maxTypeLen); 00159 WARN("m_ContentType.length()=%d", m_ContentType.length()); 00160 return !OK; 00161 } 00162 strcpy(type, m_ContentType.c_str()); 00163 return OK; 00164 } 00165 00166 /*virtual*/ bool HTTPPoster::getIsChunked() //For Transfer-Encoding header 00167 { 00168 return false; ////Data is computed one key/value pair at a time 00169 } 00170 00171 /*virtual*/ size_t HTTPPoster::getDataLen() //For Content-Length header 00172 { 00173 m_len = 0; 00174 for(int i = 0; i < m_post_data.size(); i++) { 00175 m_len += 2 + strlen(m_boundary) + 2; // "--" boundary CRLF 00176 m_len += m_post_data[i].head.size() + 2; // Content-Disposition: ... CRLF 00177 m_len += 2; // CRLF 00178 m_len += m_post_data[i].length; // value / file body 00179 m_len += 2; // CRLF 00180 } 00181 m_len += 2 + strlen(m_boundary) + 2 + 2; // "--" boundary "--" CRLF 00182 return m_len; 00183 }
Generated on Wed Jul 13 2022 04:23:07 by 1.7.2