webclient_file.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2017-07-26 chenyong modify log information
  9. */
  10. #include <stdint.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include "pika_adapter_rtt.h"
  15. #include "webclient.h"
  16. #ifdef RT_USING_DFS
  17. #include <fcntl.h>
  18. #include <unistd.h>
  19. #define DBG_ENABLE
  20. #define DBG_SECTION_NAME "web.file"
  21. #ifdef WEBCLIENT_DEBUG
  22. #define DBG_LEVEL DBG_LOG
  23. #else
  24. #define DBG_LEVEL DBG_INFO
  25. #endif /* WEBCLIENT_DEBUG */
  26. #define DBG_COLOR
  27. #include <rtdbg.h>
  28. /**
  29. * send GET request and store response data into the file.
  30. *
  31. * @param URI input server address
  32. * @param filename store response date to filename
  33. *
  34. * @return <0: GET request failed
  35. * =0: success
  36. */
  37. int webclient_get_file(const char* URI, const char* filename) {
  38. int fd = -1, rc = WEBCLIENT_OK;
  39. size_t offset;
  40. int length, total_length = 0;
  41. unsigned char* ptr = RT_NULL;
  42. struct webclient_session* session = RT_NULL;
  43. int resp_status = 0;
  44. session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
  45. if (session == RT_NULL) {
  46. rc = -WEBCLIENT_NOMEM;
  47. goto __exit;
  48. }
  49. if ((resp_status = webclient_get(session, URI)) != 200) {
  50. LOG_E("get file failed, wrong response: %d (-0x%X).", resp_status,
  51. resp_status);
  52. rc = -WEBCLIENT_ERROR;
  53. goto __exit;
  54. }
  55. fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0);
  56. if (fd < 0) {
  57. LOG_E("get file failed, open file(%s) error.", filename);
  58. rc = -WEBCLIENT_ERROR;
  59. goto __exit;
  60. }
  61. ptr = (unsigned char*)web_malloc(WEBCLIENT_RESPONSE_BUFSZ);
  62. if (ptr == RT_NULL) {
  63. LOG_E("get file failed, no memory for response buffer.");
  64. rc = -WEBCLIENT_NOMEM;
  65. goto __exit;
  66. }
  67. if (session->content_length < 0) {
  68. while (1) {
  69. length = webclient_read(session, ptr, WEBCLIENT_RESPONSE_BUFSZ);
  70. if (length > 0) {
  71. write(fd, ptr, length);
  72. total_length += length;
  73. LOG_RAW(">");
  74. } else {
  75. break;
  76. }
  77. }
  78. } else {
  79. for (offset = 0; offset < (size_t)session->content_length;) {
  80. length = webclient_read(
  81. session, ptr,
  82. session->content_length - offset > WEBCLIENT_RESPONSE_BUFSZ
  83. ? WEBCLIENT_RESPONSE_BUFSZ
  84. : session->content_length - offset);
  85. if (length > 0) {
  86. write(fd, ptr, length);
  87. total_length += length;
  88. LOG_RAW(">");
  89. } else {
  90. break;
  91. }
  92. offset += length;
  93. }
  94. }
  95. if (total_length) {
  96. LOG_D("save %d bytes.", total_length);
  97. }
  98. __exit:
  99. if (fd >= 0) {
  100. close(fd);
  101. }
  102. if (session != RT_NULL) {
  103. webclient_close(session);
  104. }
  105. if (ptr != RT_NULL) {
  106. web_free(ptr);
  107. }
  108. return rc;
  109. }
  110. /**
  111. * post file to http server.
  112. *
  113. * @param URI input server address
  114. * @param filename post data filename
  115. * @param form_data form data
  116. *
  117. * @return <0: POST request failed
  118. * =0: success
  119. */
  120. int webclient_post_file(const char* URI,
  121. const char* filename,
  122. const char* form_data) {
  123. size_t length;
  124. char boundary[60];
  125. int fd = -1, rc = WEBCLIENT_OK;
  126. char *header = RT_NULL, *header_ptr;
  127. unsigned char *buffer = RT_NULL, *buffer_ptr;
  128. struct webclient_session* session = RT_NULL;
  129. int resp_data_len = 0;
  130. fd = open(filename, O_RDONLY, 0);
  131. if (fd < 0) {
  132. LOG_D("post file failed, open file(%s) error.", filename);
  133. rc = -WEBCLIENT_FILE_ERROR;
  134. goto __exit;
  135. }
  136. /* get the size of file */
  137. length = lseek(fd, 0, SEEK_END);
  138. lseek(fd, 0, SEEK_SET);
  139. buffer = (unsigned char*)web_calloc(1, WEBCLIENT_RESPONSE_BUFSZ);
  140. if (buffer == RT_NULL) {
  141. LOG_D("post file failed, no memory for response buffer.");
  142. rc = -WEBCLIENT_NOMEM;
  143. goto __exit;
  144. }
  145. header = (char*)web_calloc(1, WEBCLIENT_HEADER_BUFSZ);
  146. if (header == RT_NULL) {
  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. web_snprintf(boundary, sizeof(boundary),
  154. "----------------------------%012d", rt_tick_get());
  155. /* build encapsulated mime_multipart information*/
  156. buffer_ptr = buffer;
  157. /* first boundary */
  158. buffer_ptr += web_snprintf((char*)buffer_ptr,
  159. WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  160. "--%s\r\n", boundary);
  161. buffer_ptr += web_snprintf(
  162. (char*)buffer_ptr, WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  163. "Content-Disposition: form-data; %s\r\n", form_data);
  164. buffer_ptr += web_snprintf(
  165. (char*)buffer_ptr, WEBCLIENT_RESPONSE_BUFSZ - (buffer_ptr - buffer),
  166. "Content-Type: application/octet-stream\r\n\r\n");
  167. /* calculate content-length */
  168. length += buffer_ptr - buffer;
  169. length += strlen(boundary) + 8; /* add the last boundary */
  170. /* build header for upload */
  171. header_ptr +=
  172. web_snprintf(header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  173. "Content-Length: %d\r\n", length);
  174. header_ptr += web_snprintf(
  175. header_ptr, WEBCLIENT_HEADER_BUFSZ - (header_ptr - header),
  176. "Content-Type: multipart/form-data; boundary=%s\r\n", boundary);
  177. session = webclient_session_create(WEBCLIENT_HEADER_BUFSZ);
  178. if (session == RT_NULL) {
  179. rc = -WEBCLIENT_NOMEM;
  180. goto __exit;
  181. }
  182. strncpy(session->header->buffer, header, strlen(header));
  183. session->header->length = strlen(session->header->buffer);
  184. rc = webclient_post(session, URI, NULL, 0);
  185. if (rc < 0) {
  186. goto __exit;
  187. }
  188. /* send mime_multipart */
  189. webclient_write(session, buffer, buffer_ptr - buffer);
  190. /* send file data */
  191. while (1) {
  192. length = read(fd, buffer, WEBCLIENT_RESPONSE_BUFSZ);
  193. if (length <= 0) {
  194. break;
  195. }
  196. webclient_write(session, buffer, length);
  197. }
  198. /* send last boundary */
  199. web_snprintf((char*)buffer, WEBCLIENT_RESPONSE_BUFSZ, "\r\n--%s--\r\n",
  200. boundary);
  201. webclient_write(session, buffer, strlen(boundary) + 8);
  202. extern int webclient_handle_response(struct webclient_session * session);
  203. if (webclient_handle_response(session) != 200) {
  204. rc = -WEBCLIENT_ERROR;
  205. goto __exit;
  206. }
  207. resp_data_len = webclient_content_length_get(session);
  208. if (resp_data_len > 0) {
  209. int bytes_read = 0;
  210. web_memset(buffer, 0x00, WEBCLIENT_RESPONSE_BUFSZ);
  211. do {
  212. bytes_read = webclient_read(session, buffer,
  213. resp_data_len < WEBCLIENT_RESPONSE_BUFSZ
  214. ? resp_data_len
  215. : WEBCLIENT_RESPONSE_BUFSZ);
  216. if (bytes_read <= 0) {
  217. break;
  218. }
  219. resp_data_len -= bytes_read;
  220. } while (resp_data_len > 0);
  221. }
  222. __exit:
  223. if (fd >= 0) {
  224. close(fd);
  225. }
  226. if (session != RT_NULL) {
  227. webclient_close(session);
  228. }
  229. if (buffer != RT_NULL) {
  230. web_free(buffer);
  231. }
  232. if (header != RT_NULL) {
  233. web_free(header);
  234. }
  235. return rc;
  236. }
  237. int wget(int argc, char** argv) {
  238. if (argc != 3) {
  239. rt_kprintf("Please using: wget <URI> <filename>\n");
  240. return -1;
  241. }
  242. webclient_get_file(argv[1], argv[2]);
  243. return 0;
  244. }
  245. #ifdef FINSH_USING_MSH
  246. #include <finsh.h>
  247. MSH_CMD_EXPORT(wget, Get file by URI : wget<URI><filename>.);
  248. #endif /* FINSH_USING_MSH */
  249. #endif /* RT_USING_DFS */