定位flash上传出现IO Error #2038的错误

本文介绍了在使用Flash上传大文件时遇到IO错误#2038的问题,并详细记录了解决过程,包括调整PHP和Nginx配置的具体步骤。

在使用flash上传文件时,当文件超过一定大小,会遇到错误:

image

flash upload

 

如何遇到这个问题的:

去年曾经使用Extjs开发一个游戏运维集成系统,其中有一个功能是使用flash上传文件,例如excel、sql等,后台程序来处理上传的文件。而这个flash上传工具是我之前写的,可是同事现在在系统中上传一个2M多的文件时,传到40%左右就提示出现io错误,让人查一下是否是flash有超时的情况。

看到这个问题我也觉得很奇怪,因为flash在选择文件的后就判定它的大小了,所以flash不存在文件过大或过小的情况。而flash向后台提交参数是否存在超时,我第一反应是不存在(除非http协议或是web服务器上面有超时限制);flash做的只是监听和回调

 

那问题出在哪里,最初我认识是后台服务器的问题,比如上传大小的设置限制等。因为后台使用java写的,本机不太好模拟环境,只能自己用php模拟后台来找到这个问题

 

为了保险起见,我用了两种方案:

1、普通的form提交

2、flash的post提交

 

最初试的时候,用fiddler抓到的是请求php得到http的504错误(GameWay timeout,奇怪了…)

然后去验证自己的想法,是否php里有设置文件大小的参数,找到php.ini,修改如下参数:

upload_max_filesize = 200M
post_max_size = 200M

(如果以上两项设定的值小于post提交文件大小,将得不到文件的相关信息,如temp_name、size等,但不会出现flash io error 2038,反复测试得到的结果)

当然还有其它参数需要修改,如:max_execution_time、max_input_time等.

详情请参考:php.ini修改php上传文件大小限制

 

即使是我修改memory_limit=-1,修改所有php参数依旧出现错误,然后继续搜索

在swfupload的官网论坛里找到这么一篇关于IO Error #2038

仔细阅读了下面的回复,看到有一条比较吸引人:

“Hello. I use nginx proxy and i see same error. I fixed in my site and now working fine.”

为何如此吸引我,因为我本机的web服务器也使用的也是nginx

读完以后,就先试试了,调参数,它上面的三个参数我都改了:

#keepalive_timeout  60;
#send_timeout 3m;
client_max_body_size 500m;

注释前面两个,修改最后一项为500m,默认大小好像是1m

 

它给出的示例配置如下:

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
sendfile on;
client_max_body_size 500m;
tcp_nodelay on;
gzip on;
server {
listen 80;
server_name domain.hu www.domain.hu;
access_log off;
location / {
proxy_pass http://xxxxxxxxxx:80/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/nginx-default;
}
}
}

关闭nginx应用程序,再重启它,刷新、测试,居然好了…

 

好了以后,再反向推导产生问题的原因,先还原所有参数,再一个一个试,最终找到关键点:client_max_body_size这个参数

如果设置的大小过小,则会出现413 Request Entity Too Large错误(之前是504,这也让我很奇怪,前面没截到图---遗憾)

normal upload

 

image

 

确定是nginx的问题,然后回头又折腾php的几个参数,发现:如果upload_max_filesize或post_max_size的值比上传的文件要小,则将获取不到文件的相关信息,但不报错。

$_FILES["Filedata"]["error"] == 0;

print_r($_FILES);

image

 

至于换成Apache是否会遇到这个问题,我就不清楚了,没测试过~

#include "esp_http_server.h" #include "esp_timer.h" #include "img_converters.h" #include "fb_gfx.h" #include "esp32-hal-ledc.h" #include "sdkconfig.h" #include "esp_camera.h" #include <WiFi.h> #include "soc/soc.h" #include "soc/rtc_cntl_reg.h" // 根据厂家提供的引脚定义修改 #define PWDN_GPIO_NUM -1 // 未使用 #define RESET_GPIO_NUM -1 // 未使用 #define XCLK_GPIO_NUM 15 // CAM_XCLK -> IO15 #define SIOD_GPIO_NUM 4 // CAM_SIDO -> IO4 #define SIOC_GPIO_NUM 5 // CAM_SIOC -> IO5 #define Y9_GPIO_NUM 16 // CAM_Y9 -> IO16 #define Y8_GPIO_NUM 17 // CAM_Y8 -> IO17 #define Y7_GPIO_NUM 18 // CAM_Y7 -> IO18 #define Y6_GPIO_NUM 12 // CAM_Y6 -> IO12 #define Y5_GPIO_NUM 10 // CAM_Y5 -> IO10 #define Y4_GPIO_NUM 8 // CAM_Y4 -> IO8 #define Y3_GPIO_NUM 9 // CAM_Y3 -> IO9 #define Y2_GPIO_NUM 11 // CAM_Y2 -> IO11 #define VSYNC_GPIO_NUM 6 // CAM_VYSNC -> IO6 #define HREF_GPIO_NUM 7 // CAM_HREF -> IO7 #define PCLK_GPIO_NUM 13 // CAM_PCLK -> IO13 // =========================== // 输入您的WiFi凭据 // =========================== const char *ssid = "a304"; const char *password = "a12345678"; // void startCameraServer(); void setupLedFlash(int pin); void setup() { // 禁用 brownout 检测器 WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); Serial.begin(115200); Serial.setDebugOutput(true); Serial.println(); camera_config_t config; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sccb_sda = SIOD_GPIO_NUM; config.pin_sccb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; // 用于流媒体 //config.pixel_format = PIXFORMAT_RGB565; // 用于人脸检测/识别 config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; // 如果存在PSRAM IC,使用UXGA分辨率和更高的JPEG质量初始化 // 用于更大的预分配帧缓冲区 if (config.pixel_format == PIXFORMAT_JPEG) { if (psramFound()) { config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; } else { // 当PSRAM不可用时限制帧大小 config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; } } else { // 人脸检测/识别的最佳选项 config.frame_size = FRAMESIZE_240X240; #if CONFIG_IDF_TARGET_ESP32S3 config.fb_count = 2; #endif } // 摄像头初始化 esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("摄像头初始化失败,错误代码: 0x%x", err); return; } sensor_t *s = esp_camera_sensor_get(); // 初始传感器垂直翻转且颜色有点饱和 if (s->id.PID == OV2640_PID) { s->set_vflip(s, 1); // 翻转回来 s->set_brightness(s, 1); // 提高亮度 s->set_saturation(s, -2); // 降低饱和度 } // 降低帧大小以获得更高的初始帧率 if (config.pixel_format == PIXFORMAT_JPEG) { s->set_framesize(s, FRAMESIZE_QVGA); } // 连接WiFi WiFi.begin((char*)ssid, (char*)password); // WiFi.setSleep(false); // 这行可能需要移除,因为新版本WiFi库可能不支持 while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi已连接"); startCameraServer(); Serial.print("摄像头准备就绪! 使用 &#39;http://"); Serial.print(WiFi.localIP()); Serial.println("&#39; 连接"); } void loop() { // 什么都不做。所有工作都由Web服务器在另一个任务中完成 delay(10000); } void startCameraServer() { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.server_port = 80; config.ctrl_port = 80; config.max_open_sockets = 1; // 减少最大连接数 httpd_handle_t server = NULL; Serial.printf("启动网络服务器端口: &#39;%d&#39;\n", config.server_port); if (httpd_start(&server, &config) == ESP_OK) { // 注册基本的请求处理程序 httpd_uri_t index_uri = { .uri = "/", .method = HTTP_GET, .handler = [](httpd_req_t *req){ const char* html = "<html><head><title>ESP32摄像头</title></head>" "<body><h1>ESP32摄像头服务器</h1>" "<p><a href=&#39;/stream&#39;>查看视频流</a></p>" "</body></html>"; httpd_resp_set_type(req, "text/html"); return httpd_resp_send(req, html, strlen(html)); }, .user_ctx = NULL }; httpd_register_uri_handler(server, &index_uri); Serial.println("HTTP服务器启动成功"); } else { Serial.println("HTTP服务器启动失败"); } } 我上传到开发板 我怎么样才可以打开 查看摄像头呢load:0x3fce2820,len:0x1150 load:0x403c8700,len:0x4 load:0x403c8704,len:0xc24 load:0x403cb700,len:0x30b4 entry 0x403c88b8 ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x3 (RTC_SW_SYS_RST),boot:0x9 (SPI_FAST_FLASH_BOOT) Saved PC:0x40376a6a SPIWP:0xee mode:DIO, clock div:1 load:0x3fce2820,len:0x1150 load:0x403c8700,len:0x4 load:0x403c8704,len:0xc24 load:0x403cb700,len:0x30b4 entry 0x403c88b8 ESP-ROM:esp32s3-20210327 Build:Mar 27 2021 rst:0x3 (RTC_SW_SYS_RST),boot:0x9 (SPI_FAST_FLASH_BOOT) Saved PC:0x40376a6a SPIWP:0xee mode:DIO, clock div:1 load:0x3fce2820,len:0x1150 load:0x403c8700,len:0x4 总是输出这些
最新发布
09-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值