How do we upload files

Struts2文件上传指南
本文介绍了如何使用Struts2框架进行文件上传操作,包括利用MultipartRequestWrapper和fileUpload拦截器的方法。此外还详细说明了如何处理多个文件上传及配置相关属性。
xml 代码
  1. How do we upload files   
  2.  Edit Page    Browse Space    Add Page    Add News    
  3. Added by tm_jee, last edited by Ted Husted on Jan 28, 2007  (view change)    
  4. You can obtain the MultipartRequestWrapper from the ServletActionContext or by utilizing the fileUpload interceptor. The fileUpload interceptor is preferred.   
  5.   
  6. Ask the ServletActionContext   
  7. MultipartRequestWrapper multipartRequest = ((MultipartRequestWrapper)ServletActionContext.getRequest())   
  8. The MultipartRequestWrapper provideds access methods such as getFiles, getFile, getContentType, hasErrors, getErrors, and so forth, so that you can process the file uploaded.   
  9.   
  10. Utilize the fileUpload Interceptor   
  11.  _Preferred_   
  12.   
  13. Ensure that {{fileUpload }} Interceptor is included in the Action's stack.    
  14.  The default stack already includes {{fileUpload }}.    
  15. Ensure that the HTML form sets the enctype and specifies on or more file type inputs.    
  16. <form name="myForm" enctype="multipart/form-data">  
  17.      <input type="file" name="myDoc" value="Browse ..." />  
  18.      <input type="submit" />  
  19.   </form>  
  20. Ensure that the Action provides one or more fileUpload mutator methods, with names that correspond to name of the file type input.    
  21. public void setMyDoc(File myDoc)   
  22. public void setMyDocContentType(String contentType)   
  23. public void setMyDocFileName(String filename)   
  24. The Action may also provide the corresponding accessor methods.    
  25. public File getMyDoc()   
  26. public ContentType getMyDocContentType()   
  27. public String getMyDocFileName()   
  28. Handling multiple files   
  29. When multiple files are uploaded by a form, the files are represented by an array.   
  30.   
  31. Given:   
  32.   
  33. <form name="myForm" enctype="multipart/form-data">  
  34.       <input type="file" name="myDoc" value="Browse File A ..." />  
  35.       <input type="file" name="myDoc" value="Browse File B ..." />  
  36.       <input type="file" name="myDoc" value="Browse File C ..." />  
  37.       <input type="submit" />  
  38.    </form>  
  39. The Action class can define file handling methods that accept an array.   
  40.   
  41. public void setMyDoc(File[] myDocs)   
  42. public void setMyDocContentType(String[] contentTypes)   
  43. public void setMyDocFileName(String[] fileNames)   
  44. The uploaded files can be handled by iterating through the appropriate array.   
  45.   
  46. Extra Information   
  47. Property  Default     
  48. struts.multipart.parser  Commons FileUpload     
  49. struts.multipart.saveDir  javax.servlet.context.tempdir as defined by container     
  50. struts.multipart.maxSize  Approximately 2M     
  51.   
  52. @see struts.properties   
  53. @see org.apache.struts2.dispatcher.FilterDispatcher#doFilter(SerlvetRequest, ServletRepsonse, FilterChain)   
  54. @see org.apache.struts2.dispatcher.DispatcherUtil#wrapRequest(HttpServletRequest, SerlvetContext)   
  55. @see org.apache.struts2.dispatcher.multipart.MultipartRequestWrapper   
  56. @see org.apache.struts2.interceptor.FileUploadInterceptor   
  57.   
#include "uip.h" #include "httpd.h" #include "fs.h" #include "fsdata.h" #include "common.h" DECLARE_GLOBAL_DATA_PTR; #define DEV_NAME_ADDR 0x1da02 #define HW_VER_ADDR 0x1da40 #define MAX_DEV_NAME_SIZE 55 #define MAX_HW_VER_SIZE 14 #define STATE_NONE 0 // empty state (waiting for request...) #define STATE_FILE_REQUEST 1 // remote host sent GET request #define STATE_UPLOAD_REQUEST 2 // remote host sent POST request // ASCII characters #define ISO_G 0x47 // GET #define ISO_E 0x45 #define ISO_T 0x54 #define ISO_P 0x50 // POST #define ISO_O 0x4f #define ISO_S 0x53 #define ISO_T 0x54 #define ISO_slash 0x2f // control and other characters #define ISO_space 0x20 #define ISO_nl 0x0a #define ISO_cr 0x0d #define ISO_tab 0x09 // we use this so that we can do without the ctype library #define is_digit(c) ((c) >= '0' && (c) <= '9') // debug //#define DEBUG_UIP // html files extern const struct fsdata_file file_index_html; extern const struct fsdata_file file_404_html; extern const struct fsdata_file file_flashing_html; extern const struct fsdata_file file_fail_html; extern int webfailsafe_ready_for_upgrade; extern int webfailsafe_firmware_chk_success; #ifdef CONFIG_RTS3913 extern u32 net_boot_file_size; #else extern ulong NetBootFileXferSize; #endif extern unsigned char *webfailsafe_data_pointer; // http app state struct httpd_state *hs; static int webfailsafe_post_done = 0; static int webfailsafe_upload_failed = 0; static unsigned char post_packet_counter = 0; // 0x0D -> CR 0x0A -> LF static char eol[3] = { 0x0d, 0x0a, 0x00 }; static char eol2[5] = { 0x0d, 0x0a, 0x0d, 0x0a, 0x00 }; static char *boundary_value; // str to int static int atoi(const char *s){ int i = 0; while(is_digit(*s)){ i = i * 10 + *(s++) - '0'; } return(i); } // print downloading progress static void httpd_download_progress(void){ if(post_packet_counter == 194){ puts("\n "); post_packet_counter = 0; } if (post_packet_counter%3 == 0) puts("#"); post_packet_counter++; } // http server init void httpd_init(void) { fs_init(); upgrade_init(); uip_listen(HTONS(HTTPD_LISTEN_PORT)); } // reset app state static void httpd_state_reset(void){ hs->state = STATE_NONE; hs->count = 0; hs->dataptr = 0; hs->upload = 0; hs->upload_total = 0; hs->data_start_found = 0; post_packet_counter = 0; if(boundary_value){ free(boundary_value); boundary_value = NULL; } } // find and get first chunk of data static int httpd_findandstore_firstchunk(void){ char *start = NULL; char *end = NULL; if(!boundary_value){ return(0); } // chek if we have data in packet start = (char *)strstr((char *)uip_appdata, (char *)boundary_value); if(start){ // ok, we have data in this packet! // find start position of the data! end = (char *)strstr((char *)start, eol2); if(end){ if((end - (char *)uip_appdata) < uip_len){ // move pointer over CR LF CR LF end += 4; // how much data we expect? // last part (magic value 6): [CR][LF](boundary length)[-][-][CR][LF] hs->upload_total = hs->upload_total - (int)(end - start) - strlen(boundary_value) - 6; printf("Upload file size: %d bytes\n", hs->upload_total); printf("Loading: "); // how much data we are storing now? hs->upload = (unsigned int)(uip_len - (end - (char *)uip_appdata)); memcpy((void *)webfailsafe_data_pointer, (void *)end, hs->upload); webfailsafe_data_pointer += hs->upload; httpd_download_progress(); return(1); } } else { printf("## Error: couldn't find start of data!\n"); } } return(0); } static int httpd_get_model(char model[MAX_DEV_NAME_SIZE + MAX_HW_VER_SIZE + 2]) { if (model == NULL) { printf("## Error: null parameter when get model\n"); return -1; } char dev_name[MAX_DEV_NAME_SIZE + 1] = {0}; char hw_ver[MAX_HW_VER_SIZE + 1] = {0}; if (readFlash(DEV_NAME_ADDR, dev_name, MAX_DEV_NAME_SIZE) || !strlen(dev_name)) { printf("## Error: couldn't find dev name!\n"); return -1; } if (readFlash(HW_VER_ADDR, hw_ver, MAX_HW_VER_SIZE) || !strlen(hw_ver)) { printf("## Error: couldn't find hw ver!\n"); return -1; } sprintf(model, "%s %s", dev_name, hw_ver); return 0; } static int httpd_replace_model(struct fs_file *fsfile, char *model) { if ((fsfile == NULL) || (model == NULL)) { printf("## Error: null parameter replace mode\n"); return -1; } int i = 0; int j = 0; char tag[] = "hardwareVer"; int tag_len = strlen(tag); int model_len = strlen(model); for (i = 0; i < fsfile->len; i++) { j = (tag[j] == fsfile->data[i])? (j + 1): 0; if (j == tag_len) { break; } } i += 1 + strlen("\">"); j = 0; while ((i < fsfile->len) && (fsfile->data[i] != '<')) { if (j < model_len) { fsfile->data[i++] = model[j++]; } else { fsfile->data[i++] = ISO_space; } } return 0; } // called for http server app void httpd_appcall(void){ struct fs_file fsfile; unsigned int i; switch(uip_conn->lport){ case HTONS(80): // app state hs = (struct httpd_state *)(uip_conn->appstate); // closed connection if(uip_closed()){ httpd_state_reset(); uip_close(); return; } // aborted connection or time out occured if(uip_aborted() || uip_timedout()){ httpd_state_reset(); uip_abort(); return; } // if we are pooled if(uip_poll()){ if(hs->count++ >= 100){ httpd_state_reset(); uip_abort(); } return; } // new connection if(uip_connected()){ httpd_state_reset(); return; } // new data in STATE_NONE if(uip_newdata() && hs->state == STATE_NONE){ // GET or POST request? if( ((u8_t*)uip_appdata)[0] == ISO_G && ((u8_t*)uip_appdata)[1] == ISO_E && ((u8_t*)uip_appdata)[2] == ISO_T && (((u8_t*)uip_appdata)[3] == ISO_space || ((u8_t*)uip_appdata)[3] == ISO_tab)) { hs->state = STATE_FILE_REQUEST; } else if(((u8_t*)uip_appdata)[0] == ISO_P && ((u8_t*)uip_appdata)[1] == ISO_O && ((u8_t*)uip_appdata)[2] == ISO_S && ((u8_t*)uip_appdata)[3] == ISO_T && (((u8_t*)uip_appdata)[4] == ISO_space || ((u8_t*)uip_appdata)[4] == ISO_tab)){ hs->state = STATE_UPLOAD_REQUEST; } // anything else -> abort the connection! if(hs->state == STATE_NONE) { httpd_state_reset(); uip_abort(); return; } // get file or firmware upload? if(hs->state == STATE_FILE_REQUEST){ // we are looking for GET file name for(i = 4; i < 30; i++){ if( ((u8_t*)uip_appdata)[i] == ISO_space || ((u8_t*)uip_appdata)[i] == ISO_cr || ((u8_t*)uip_appdata)[i] == ISO_nl || ((u8_t*)uip_appdata)[i] == ISO_tab){ ((u8_t*)uip_appdata)[i] = 0; i = 0; break; } } if(i != 0){ printf("## Error: request file name too long!\n"); httpd_state_reset(); uip_abort(); return; } printf("rport:%d; Request for: ", uip_conn->rport); printf("%s\n", &((u8_t*)uip_appdata)[4]); // request for / if(((u8_t*)uip_appdata)[4] == ISO_slash && ((u8_t*)uip_appdata)[5] == 0){ i = fs_open(file_index_html.name, &fsfile); char model[MAX_DEV_NAME_SIZE + MAX_HW_VER_SIZE + 2] = {0}; if (!httpd_get_model(model)) { httpd_replace_model(&fsfile, model); } } else { // check if we have requested file if(!fs_open((const char *)&((u8_t*)uip_appdata)[4], &fsfile)){ printf("## Error: file not found!\n"); fs_open(file_404_html.name, &fsfile); } } hs->state = STATE_FILE_REQUEST; hs->dataptr = (u8_t *)fsfile.data; hs->upload = fsfile.len; // send first (and maybe the last) chunk of data uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload)); return; } else if(hs->state == STATE_UPLOAD_REQUEST) { char *start = NULL; char *end = NULL; // end bufor data with NULL ((u8_t*)uip_appdata)[uip_len] = '\0'; /* * We got first packet with POST request * * Some browsers don't include first chunk of data in the first * POST request packet (like Google Chrome, IE and Safari)! * So we must now find two values: * - Content-Length * - boundary * Headers with these values can be in any order! * If we don't find these values in first packet, connection will be aborted! * */ // Content-Length pos start = (char *)strstr((char*)uip_appdata, "Content-Length:"); if(start){ start += sizeof("Content-Length:"); // find end of the line with "Content-Length:" end = (char *)strstr(start, eol); if(end){ hs->upload_total = atoi(start); #ifdef DEBUG_UIP printf("Expecting %d bytes in body request message\n", hs->upload_total); #endif } else { printf("## Error: couldn't find \"Content-Length\"!\n"); httpd_state_reset(); uip_abort(); return; } } else { printf("## Error: couldn't find \"Content-Length\"!\n"); httpd_state_reset(); uip_abort(); return; } // we don't support very small files (< 10 KB) if(hs->upload_total < 10240){ printf("## Error: request for upload < 10 KB data!\n"); httpd_state_reset(); uip_abort(); return; } // boundary value start = NULL; end = NULL; start = (char *)strstr((char *)uip_appdata, "boundary="); if(start){ // move pointer over "boundary=" start += 9; // find end of line with boundary value end = (char *)strstr((char *)start, eol); if(end){ // malloc space for boundary value + '--' and '\0' boundary_value = (char*)malloc(end - start + 3); if(boundary_value){ memcpy(&boundary_value[2], start, end - start); // add -- at the begin and 0 at the end boundary_value[0] = '-'; boundary_value[1] = '-'; boundary_value[end - start + 2] = 0; #ifdef DEBUG_UIP printf("Found boundary value: \"%s\"\n", boundary_value); #endif } else { printf("## Error: couldn't allocate memory for boundary!\n"); httpd_state_reset(); uip_abort(); return; } } else { printf("## Error: couldn't find boundary!\n"); httpd_state_reset(); uip_abort(); return; } } else { printf("## Error: couldn't find boundary!\n"); httpd_state_reset(); uip_abort(); return; } /* * OK, if we are here, it means that we found * Content-Length and boundary values in headers * * We can now try to 'allocate memory' and * find beginning of the data in first packet */ webfailsafe_data_pointer = (u8_t *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS; if(!webfailsafe_data_pointer){ printf("## Error: couldn't allocate RAM for data!\n"); httpd_state_reset(); uip_abort(); return; } else { printf("Data will be downloaded at 0x%X in RAM\n", WEBFAILSAFE_UPLOAD_RAM_ADDRESS); } if(httpd_findandstore_firstchunk()){ hs->data_start_found = 1; } else { hs->data_start_found = 0; } return; } /* else if(hs->state == STATE_UPLOAD_REQUEST) */ } /* uip_newdata() && hs->state == STATE_NONE */ // if we got ACK from remote host if(uip_acked()){ // if we are in STATE_FILE_REQUEST state if(hs->state == STATE_FILE_REQUEST){ // data which we send last time was received (we got ACK) // if we send everything last time -> gently close the connection if(hs->upload <= uip_mss()){ // post upload completed? if(webfailsafe_post_done){ if(!webfailsafe_upload_failed){ webfailsafe_ready_for_upgrade = 1; } webfailsafe_post_done = 0; webfailsafe_upload_failed = 0; } httpd_state_reset(); uip_close(); return; } // otherwise, send another chunk of data // last time we sent uip_conn->len size of data hs->dataptr += uip_conn->len; hs->upload -= uip_conn->len; UIP_LOG("line: %d==:rport:%d;hs->upload %d; " "last send uip_conn->len %d;" "now will send %d;" " --debug by HouXB\n", __LINE__, uip_conn->rport, hs->upload, uip_conn->len, (hs->upload > uip_mss() ? uip_mss() : hs->upload)); uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload)); } return; } // if we need to retransmit if(uip_rexmit()){ // if we are in STATE_FILE_REQUEST state if(hs->state == STATE_FILE_REQUEST){ // send again chunk of data without changing pointer and length of data left to send uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload)); } return; } // if we got new data frome remote host if(uip_newdata()){ // if we are in STATE_UPLOAD_REQUEST state if(hs->state == STATE_UPLOAD_REQUEST){ // end bufor data with NULL ((u8_t*)uip_appdata)[uip_len] = '\0'; // do we have to find start of data? if(!hs->data_start_found){ if(!httpd_findandstore_firstchunk()){ printf("## Error: couldn't find start of data in next packet!\n"); httpd_state_reset(); uip_abort(); return; } else { hs->data_start_found = 1; } return; } hs->upload += (unsigned int)uip_len; if(!webfailsafe_upload_failed){ memcpy((void *)webfailsafe_data_pointer, (void *)uip_appdata, uip_len); webfailsafe_data_pointer += uip_len; } httpd_download_progress(); // if we have collected all data if(hs->upload >= hs->upload_total){ printf("\n\n"); // end of post upload webfailsafe_post_done = 1; #ifdef CONFIG_RTS3913 net_boot_file_size = (ulong)hs->upload_total; if(do_http_check(net_boot_file_size)<0) #else NetBootFileXferSize = (ulong)hs->upload_total; if(do_http_check(NetBootFileXferSize)<0) #endif { webfailsafe_upload_failed = 1; } else { webfailsafe_firmware_chk_success = 1; } // which website will be returned if(!webfailsafe_upload_failed){ fs_open(file_flashing_html.name, &fsfile); } else { fs_open(file_fail_html.name, &fsfile); } httpd_state_reset(); hs->state = STATE_FILE_REQUEST; hs->dataptr = (u8_t *)fsfile.data; hs->upload = fsfile.len; uip_send(hs->dataptr, (hs->upload > uip_mss() ? uip_mss() : hs->upload)); } } return; } break; default: // we shouldn't get here... we are listening only on port 80 uip_abort(); break; } }
09-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值