webclient_file.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * File : webclient_file.c
  3. * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. *
  19. * Change Logs:
  20. * Date Author Notes
  21. * 2017-07-26 chenyong modify log information
  22. */
  23. #include <stdint.h>
  24. #include <stdlib.h>
  25. #include <rtthread.h>
  26. #include "webclient.h"
  27. #ifdef RT_USING_DFS
  28. #include <dfs_posix.h>
  29. /**
  30. * send GET request and store response data into the file.
  31. *
  32. * @param URI input server address
  33. * @param filename store response date to filename
  34. *
  35. * @return <0: GET request failed
  36. * =0: success
  37. */
  38. int webclient_get_file(const char* URI, const char* filename)
  39. {
  40. int fd = -1, rc = WEBCLIENT_OK;
  41. size_t offset;
  42. size_t length, total_length = 0;
  43. unsigned char *ptr = RT_NULL;
  44. struct webclient_session* session = RT_NULL;
  45. session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
  46. if(session == RT_NULL)
  47. {
  48. rc = -WEBCLIENT_NOMEM;
  49. goto __exit;
  50. }
  51. if (webclient_get(session, URI, RT_NULL) != 200)
  52. {
  53. LOG_E("get file failed, wrong response: %d.", session->response);
  54. rc = -WEBCLIENT_ERROR;
  55. goto __exit;
  56. }
  57. fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0);
  58. if (fd < 0)
  59. {
  60. LOG_E("get file failed, open file(%s) error.", filename);
  61. rc = -WEBCLIENT_ERROR;
  62. goto __exit;
  63. }
  64. ptr = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  65. if (ptr == RT_NULL)
  66. {
  67. LOG_E("get file failed, no memory for response buffer.");
  68. rc = -WEBCLIENT_NOMEM;
  69. goto __exit;
  70. }
  71. if (session->content_length == 0)
  72. {
  73. while (1)
  74. {
  75. length = webclient_read(session, ptr, WEBCLIENT_RESPONSE_BUFSZ);
  76. if (length > 0)
  77. {
  78. write(fd, ptr, length);
  79. total_length += length;
  80. rt_kprintf(">");
  81. }
  82. else
  83. {
  84. break;
  85. }
  86. }
  87. }
  88. else
  89. {
  90. for (offset = 0; offset < session->content_length;)
  91. {
  92. length = webclient_read(session, ptr,
  93. session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ ?
  94. WEBCLIENT_RESPONSE_BUFSZ : session->content_length - offset);
  95. if (length > 0)
  96. {
  97. write(fd, ptr, length);
  98. total_length += length;
  99. rt_kprintf(">");
  100. }
  101. else
  102. {
  103. break;
  104. }
  105. offset += length;
  106. }
  107. }
  108. if (total_length)
  109. {
  110. LOG_D("save %d bytes.", total_length);
  111. }
  112. __exit:
  113. if (fd >= 0)
  114. {
  115. close(fd);
  116. }
  117. if (session != RT_NULL)
  118. {
  119. webclient_close(session);
  120. }
  121. if (ptr != RT_NULL)
  122. {
  123. web_free(ptr);
  124. }
  125. return rc;
  126. }
  127. /**
  128. * post file to http server.
  129. *
  130. * @param URI input server address
  131. * @param filename post data filename
  132. * @param form_data form data
  133. *
  134. * @return <0: POST request failed
  135. * =0: success
  136. */
  137. int webclient_post_file(const char* URI, const char* filename,
  138. const char* form_data)
  139. {
  140. size_t length;
  141. char boundary[60];
  142. int fd = -1, rc = WEBCLIENT_OK;
  143. char *header = RT_NULL, *header_ptr;
  144. unsigned char *buffer = RT_NULL, *buffer_ptr;
  145. struct webclient_session* session = RT_NULL;
  146. fd = open(filename, O_RDONLY, 0);
  147. if (fd < 0)
  148. {
  149. LOG_D("post file failed, open file(%s) error.", filename);
  150. rc = -WEBCLIENT_FILE_ERROR;
  151. goto __exit;
  152. }
  153. /* get the size of file */
  154. length = lseek(fd, 0, SEEK_END);
  155. lseek(fd, 0, SEEK_SET);
  156. buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  157. if (buffer == RT_NULL)
  158. {
  159. LOG_D("post file failed, no memory for response buffer.");
  160. rc = -WEBCLIENT_NOMEM;
  161. goto __exit;
  162. }
  163. header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ);
  164. if (header == RT_NULL)
  165. {
  166. LOG_D("post file failed, no memory for header buffer.");
  167. rc = -WEBCLIENT_NOMEM;
  168. goto __exit;
  169. }
  170. header_ptr = header;
  171. /* build boundary */
  172. rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());
  173. /* build encapsulated mime_multipart information*/
  174. buffer_ptr = buffer;
  175. /* first boundary */
  176. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  177. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);
  178. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  179. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  180. "Content-Disposition: form-data; %s\r\n", form_data);
  181. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  182. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  183. "Content-Type: application/octet-stream\r\n\r\n");
  184. /* calculate content-length */
  185. length += buffer_ptr - buffer;
  186. length += strlen(boundary) + 6; /* add the last boundary */
  187. /* build header for upload */
  188. header_ptr += rt_snprintf(header_ptr,
  189. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  190. "Content-Length: %d\r\n", length);
  191. header_ptr += rt_snprintf(header_ptr,
  192. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  193. "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
  194. session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
  195. if(session == RT_NULL)
  196. {
  197. rc = -WEBCLIENT_NOMEM;
  198. goto __exit;
  199. }
  200. rc = webclient_post(session, URI, header, NULL);
  201. if( rc< 0)
  202. {
  203. goto __exit;
  204. }
  205. /* send mime_multipart */
  206. webclient_write(session, buffer, buffer_ptr - buffer);
  207. /* send file data */
  208. while (1)
  209. {
  210. length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
  211. if (length <= 0)
  212. {
  213. break;
  214. }
  215. webclient_write(session, buffer, length);
  216. }
  217. /* send last boundary */
  218. rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
  219. webclient_write(session, buffer, strlen(boundary) + 6);
  220. __exit:
  221. if (fd >= 0)
  222. {
  223. close(fd);
  224. }
  225. if (session != RT_NULL)
  226. {
  227. webclient_close(session);
  228. }
  229. if (buffer != RT_NULL)
  230. {
  231. web_free(buffer);
  232. }
  233. if (header != RT_NULL)
  234. {
  235. web_free(header);
  236. }
  237. return 0;
  238. }
  239. int wget(int argc, char** argv)
  240. {
  241. if (argc != 3)
  242. {
  243. rt_kprintf("Please using: wget <URI> <filename>");
  244. return -1;
  245. }
  246. webclient_get_file(argv[1], argv[2]);
  247. return 0;
  248. }
  249. #ifdef FINSH_USING_MSH
  250. #include <finsh.h>
  251. MSH_CMD_EXPORT(wget, Get file by URI: wget <URI> <filename>.);
  252. #endif /* FINSH_USING_MSH */
  253. #endif /* RT_USING_DFS */