webclient_file.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. int webclient_get_file(const char* URI, const char* filename)
  30. {
  31. int fd = -1, rc = WEBCLIENT_OK;
  32. size_t offset;
  33. size_t length, total_length = 0;
  34. unsigned char *ptr = RT_NULL;
  35. struct webclient_session* session = RT_NULL;
  36. session = webclient_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
  37. if(session == RT_NULL)
  38. {
  39. rc = -WEBCLIENT_NOMEM;
  40. goto __exit;
  41. }
  42. if (webclient_get(session, URI, RT_NULL) != 200)
  43. {
  44. LOG_E("get file failed, wrong response: %d.", session->response);
  45. rc = -WEBCLIENT_ERROR;
  46. goto __exit;
  47. }
  48. fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0);
  49. if (fd < 0)
  50. {
  51. LOG_E("get file failed, open file(%s) error.", filename);
  52. rc = -WEBCLIENT_ERROR;
  53. goto __exit;
  54. }
  55. ptr = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  56. if (ptr == RT_NULL)
  57. {
  58. LOG_E("get file failed, no memory for response buffer.");
  59. rc = -WEBCLIENT_NOMEM;
  60. goto __exit;
  61. }
  62. if (session->content_length == 0)
  63. {
  64. while (1)
  65. {
  66. length = webclient_read(session, ptr, WEBCLIENT_RESPONSE_BUFSZ);
  67. if (length > 0)
  68. {
  69. write(fd, ptr, length);
  70. total_length += length;
  71. rt_kprintf(">");
  72. }
  73. else
  74. {
  75. break;
  76. }
  77. }
  78. }
  79. else
  80. {
  81. for (offset = 0; offset < session->content_length;)
  82. {
  83. length = webclient_read(session, ptr,
  84. session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ ?
  85. WEBCLIENT_RESPONSE_BUFSZ : session->content_length - offset);
  86. if (length > 0)
  87. {
  88. write(fd, ptr, length);
  89. total_length += length;
  90. rt_kprintf(">");
  91. }
  92. else
  93. {
  94. break;
  95. }
  96. offset += length;
  97. }
  98. }
  99. if (total_length)
  100. {
  101. LOG_D("save %d bytes.", total_length);
  102. }
  103. __exit:
  104. if (fd >= 0)
  105. {
  106. close(fd);
  107. }
  108. if (session != RT_NULL)
  109. {
  110. webclient_close(session);
  111. }
  112. if (ptr != RT_NULL)
  113. {
  114. web_free(ptr);
  115. }
  116. return rc;
  117. }
  118. int webclient_post_file(const char* URI, const char* filename,
  119. const char* form_data)
  120. {
  121. size_t length;
  122. char boundary[60];
  123. int fd = -1, rc = WEBCLIENT_OK;
  124. char *header = RT_NULL, *header_ptr;
  125. unsigned char *buffer = RT_NULL, *buffer_ptr;
  126. struct webclient_session* session = RT_NULL;
  127. fd = open(filename, O_RDONLY, 0);
  128. if (fd < 0)
  129. {
  130. LOG_D("post file failed, open file(%s) error.", filename);
  131. rc = -WEBCLIENT_FILE_ERROR;
  132. goto __exit;
  133. }
  134. /* get the size of file */
  135. length = lseek(fd, 0, SEEK_END);
  136. lseek(fd, 0, SEEK_SET);
  137. buffer = (unsigned char *) web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  138. if (buffer == RT_NULL)
  139. {
  140. LOG_D("post file failed, no memory for response buffer.");
  141. rc = -WEBCLIENT_NOMEM;
  142. goto __exit;
  143. }
  144. header = (char *) web_malloc(WEBCLIENT_HEADER_BUFSZ);
  145. if (header == RT_NULL)
  146. {
  147. LOG_D("post file failed, no memory for header buffer.");
  148. rc = -WEBCLIENT_NOMEM;
  149. goto __exit;
  150. }
  151. header_ptr = header;
  152. /* build boundary */
  153. rt_snprintf(boundary, sizeof(boundary), "----------------------------%012d", rt_tick_get());
  154. /* build encapsulated mime_multipart information*/
  155. buffer_ptr = buffer;
  156. /* first boundary */
  157. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  158. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer), "--%s\r\n", boundary);
  159. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  160. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  161. "Content-Disposition: form-data; %s\r\n", form_data);
  162. buffer_ptr += rt_snprintf((char*) buffer_ptr,
  163. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  164. "Content-Type: application/octet-stream\r\n\r\n");
  165. /* calculate content-length */
  166. length += buffer_ptr - buffer;
  167. length += strlen(boundary) + 6; /* add the last boundary */
  168. /* build header for upload */
  169. header_ptr += rt_snprintf(header_ptr,
  170. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  171. "Content-Length: %d\r\n", length);
  172. header_ptr += rt_snprintf(header_ptr,
  173. WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  174. "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
  175. session = webclient_create(WEBCLIENT_HEADER_BUFSZ, WEBCLIENT_RESPONSE_BUFSZ);
  176. if(session == RT_NULL)
  177. {
  178. rc = -WEBCLIENT_NOMEM;
  179. goto __exit;
  180. }
  181. rc = webclient_post_header(session, URI, header);
  182. if( rc< 0)
  183. {
  184. goto __exit;
  185. }
  186. /* send mime_multipart */
  187. webclient_write(session, buffer, buffer_ptr - buffer);
  188. /* send file data */
  189. while (1)
  190. {
  191. length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
  192. if (length <= 0)
  193. {
  194. break;
  195. }
  196. webclient_write(session, buffer, length);
  197. }
  198. /* send last boundary */
  199. rt_snprintf((char*) buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n", boundary);
  200. webclient_write(session, buffer, strlen(boundary) + 6);
  201. __exit:
  202. if (fd >= 0)
  203. {
  204. close(fd);
  205. }
  206. if (session != RT_NULL)
  207. {
  208. webclient_close(session);
  209. }
  210. if (buffer != RT_NULL)
  211. {
  212. web_free(buffer);
  213. }
  214. if (header != RT_NULL)
  215. {
  216. web_free(header);
  217. }
  218. return 0;
  219. }
  220. int wget(int argc, char** argv)
  221. {
  222. if (argc != 3)
  223. {
  224. LOG_E("wget [URI] [filename] -get file by URI.");
  225. return -1;
  226. }
  227. webclient_get_file(argv[1], argv[2]);
  228. return 0;
  229. }
  230. #ifdef FINSH_USING_MSH
  231. #include <finsh.h>
  232. MSH_CMD_EXPORT(wget, web download file);
  233. #endif /* FINSH_USING_MSH */
  234. #endif /* RT_USING_DFS */