首页 > 其他分享 >ESP32纯Cj简单实现图片上传阿里云OSS

ESP32纯Cj简单实现图片上传阿里云OSS

时间:2024-07-11 23:30:38浏览次数:17  
标签:Cj pTm OSS APP ESP iFd tm ESP32

对于嵌入式设备资源较少或者运行环境较简单的环境下,如果只是简单上传一张图片到阿里云OSS服务器的话,移植阿里云OSS的SDK就是一件性价比很低而且不一定能实现的事情了。那就得考虑自己实现一套简单的、最基础的图片上传功能。阿里云OSS提供了REST API方式的图片上传接口,即通过HTTP方式将图片PUT到OSS服务器。API接口接口可参考:https://help.aliyun.com/zh/oss/developer-reference/api-reference/?spm=a2c4g.11186623.0.0.1e436d4fztnTzz
上传一张图片到阿里云OSS服务器主要分为如下几个步骤:
1. 连接aliyun OSS服务器;
2. 生成PUT语句并发送;
3. 发送图片;
4. 接收服务器返回的操作结果,判定是否需要重传。

以下具体贴一下代码实现。

一、连接阿里云OSS服务器
`int app_oss_connect_server(void)
{
    int iFd = -1;
    struct hostent *pHostEnt = NULL;
    struct sockaddr_in struServAddr;

    pHostEnt = gethostbyname(APP_OSS_DOMAIN_NAME);
    if (NULL == pHostEnt)
    {
        ESP_LOGE(TAG, "DNS lookup failed");
        return ESP_FAIL;
    }

    iFd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == iFd)
    {
        ESP_LOGE(TAG, "Socket create error!");
        return ESP_FAIL;
    }
    
    memset(&struServAddr, 0, sizeof(struServAddr));
    struServAddr.sin_family = AF_INET;
    struServAddr.sin_port = htons(APP_OSS_CONN_PORT);
    struServAddr.sin_addr = *((struct in_addr*)pHostEnt->h_addr);
    //ESP_LOGI(TAG, "Connect to ali-oss server: %s.", inet_ntoa(struServAddr.sin_addr));

    if (0 != connect(iFd, (struct sockaddr *)&struServAddr, sizeof(struct sockaddr)))
    {
        ESP_LOGE(TAG, "Connect to ali-oss server error!");
        close(iFd);
        iFd = ESP_FAIL;
    }

    return iFd;
}`
APP_OSS_DOMAIN_NAME就是购买OSS服务分配的域名,形式如:xxxx.oss-cn-hangzhou.aliyuncs.com 

二、生成PUT语句并发送+发送图片+接收服务器答复
`int app_oss_picture_upload(int iFd)
{
    camera_fb_t *pPicFB = NULL;
    char szPicName[APP_OSS_PIC_NAME_LEN] = {0};
    char szDateTime[32] = {0};
    char szAuthStr[128] = {0};
    char szOssHeader[512] = {0};
    struct tm *pTm = NULL;

    int b64Len = 0;
    unsigned char hmac[20] = {0};
    char b64[((20 + 1) * 4) / 3] = {0};
    char b64Str[((20 + 1) * 4) / 3+1] = {0};

    int wrRet = 0;
    int wrCnt = 0;
    fd_set struFdSet;
    struct timeval struTV;
    int iRet = -1;

    pPicFB = esp_camera_fb_get();
    if (!pPicFB) {
        ESP_LOGE(TAG, "Camera capture failed");
        goto errExit;
    }

    /* Fill the header content */
    memset(&struTV, 0, sizeof(struTV));
    tTime = time(NULL);
    pTm = gmtime(&tTime);
    gettimeofday(&struTV, NULL);
    snprintf(szPicName, sizeof(szPicName), 
        "/DIR/%4d%02d%02d_%02d%02d%02d%03d.jpg", 
        pTm->tm_year+1900, pTm->tm_mon+1, pTm->tm_mday,
        pTm->tm_hour, pTm->tm_min, pTm->tm_sec, (int)((struTV.tv_usec/1000)%1000));
    app_oss_global_pic_name_set(szPicName);
    snprintf(szDateTime, sizeof(szDateTime),
        "%s, %02d %s %04d %02d:%02d:%02d GMT", 
        week[pTm->tm_wday], pTm->tm_mday, months[pTm->tm_mon], 
        pTm->tm_year+1900, pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
    snprintf(szAuthStr, sizeof(szAuthStr),
        "PUT\n\nimage/jpeg\n%s\n%s", szDateTime, szPicName);
    //ESP_LOGI(TAG, "szAuthStr: %s(%d)", szAuthStr, strlen(szAuthStr));

    hmac_sha1((unsigned char*)APP_OSS_ACCESS_KEY_SECRET, 
        strlen(APP_OSS_ACCESS_KEY_SECRET),
        (unsigned char*)szAuthStr, strlen(szAuthStr), hmac);    
    b64Len = oss_base64_encode(hmac, 20, b64);
    memcpy(b64Str, b64, b64Len);

    memset(szOssHeader, 0, APP_OSS_HEADER_BUFSIZE);
    snprintf(szOssHeader, APP_OSS_HEADER_BUFSIZE,
        "PUT %s HTTP/1.1\r\n" \
        "User-Agent: esp-idf/1.0 esp32\r\n" \
        "Host: %s\r\n" \
        "Accept: */*\r\n" \
        "Content-Length: %d\r\n" \
        "Content-Type: image/jpeg\r\n" \
        "Date: %s\r\n" \
        "Authorization: OSS %s:%s\r\n\r\n",
        szPicName, APP_OSS_DOMAIN_NAME, pPicFB->len, szDateTime, 
        APP_OSS_ACCESS_KEY_ID, b64Str);

    wrCnt = write(iFd, szOssHeader, strlen(szOssHeader));
    if (wrCnt <= 0)
    {
        ESP_LOGE(TAG, "OSS send header to server error!");
        goto errExit;
    }

    wrCnt = write(iFd, pPicFB->buf, pPicFB->len);
    if (wrCnt <= 0)
    {
        ESP_LOGE(TAG, "OSS send picture to server error!");
        goto errExit;
    }

    memset(&struTV, 0, sizeof(struTV));
    memset(&struFdSet, 0, sizeof(struFdSet));
    struTV.tv_sec = 5;
    struTV.tv_usec = 0;
    FD_ZERO(&struFdSet);
    FD_CLR(iFd, &struFdSet);
    FD_SET(iFd, &struFdSet);
    wrRet = select(iFd + 1, &struFdSet, 0, 0, &struTV);
    if (wrRet > 0)
    {
        if (FD_ISSET(iFd, &struFdSet))
        {
            memset(szOssHeader, 0, APP_OSS_HEADER_BUFSIZE);
            wrCnt = read(iFd, szOssHeader, APP_OSS_HEADER_BUFSIZE-1);
            if (wrCnt > 0)
            {
                //ESP_LOGI(TAG, "OSS Response: %s", szOssHeader);
                if (NULL != strstr(szOssHeader, "200 OK"))
                {
                    ESP_LOGI(TAG, "APP OSS upload picture ok!");
                    iRet = 0;
                }
                else
                {
                    ESP_LOGE(TAG, "APP OSS upload picture failed!");
                }
            }
            else
            {
                ESP_LOGE(TAG, "OSS read response error!");
            }
        }
    } 
    else
    {
        ESP_LOGE(TAG, "OSS wait for response select error or timeout!");
    }

errExit:

    if (pPicFB)
    {
        esp_camera_fb_return(pPicFB);
        pPicFB = NULL;
    }

    return iRet;
}`
这里最主要就是header的生成,需要注意的时日期时间还得是UTC 0时区的时间,不然服务器会报错误。
base64使用普通的那种就可以了。

对于删除图片等其他操作,流程也类似。有问题欢迎留言讨论。

谢绝转载!

标签:Cj,pTm,OSS,APP,ESP,iFd,tm,ESP32
From: https://www.cnblogs.com/kymars/p/18289141

相关文章

  • 算法金 | DL 骚操作扫盲,神经网络设计与选择、参数初始化与优化、学习率调整与正则化、
    大侠幸会,在下全网同名「算法金」0基础转AI上岸,多个算法赛Top「日更万日,让更多人享受智能乐趣」今日216/10000抱个拳,送个礼神经网络设计与选择参数初始化与优化学习率调整与正则化数据预处理与标准化训练过程与监控特定模型技巧其他训练技巧1.神经网络设计......
  • Java后端tlias员工部门管理-前后端联调-阿里云OSS-5
    当完成了员工和部门管理的两大模块的所有基本功能,那么我们接下来就先进行yml文件配置。Yml文件配置为什么要换我们需要把这个application.properties配置文件改成application.yml,因为对比了其他的配置文件的格式,有诸如一下优点中文变成???那么我们进入application.proper......
  • ESM(ESModule)和CJS(CommonJS)的区别
    ESM和CJS的区别1.CJS2.EMS3ESM与CJS的区别3.1ESM输出的是==值的引用==,CJS输出的是==值得拷贝==3.2CJS的输出是运行时加载,而ESM是编译时输出接口3.3CJS是同步加载,ESM是异步加载1.CJSNode.js模块加载规范.js或.cjs文件,使用require加载,module.exports/exports......
  • ESP32S3 N16R8, USB_STREAM UVC调试记录
    win10,vscode,idf-5.2.1,usb_stream开发板:酷世Audio800*480开发板,NT53310+GT911参考phripherals/lcd/i80-controller与usb/host/usb_camera_lcd_display编写程序出现报错:I(11034)USB_STREAM:ENUMStageSTART,SucceedI(11044)USB_STREAM:ENUMStageGET_SHORT_DE......
  • 带mac对照表的OSS截屏文件下载器
    importosimportreimportsubprocessimportoss2importtkinterastkfromtkinterimportfiledialog,messagebox,simpledialogfromtkinter.scrolledtextimportScrolledTextimportjson#MAC地址对照表文件名MAC_TO_NAME_DICT_FILE='mac_to_name_dict.json&#......
  • 下载oss2上面的屏幕截图文件的代码
    importosimportreimportoss2importtkinterastkfromtkinterimportfiledialog,messageboxfromtkinter.scrolledtextimportScrolledTextimportpicklefromtkinterimportfiledialogimportsubprocessdefon_entry_focus_in(event):#当Entry获得焦点......
  • 原生js上传图片至阿里云oss并回显,配合上个帖子的java使用
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Invoice</title>......
  • ESP32-C3模组上跑通MD5(3)
    接前一篇文章:ESP32-C3模组上跑通MD5(2)本文内容参考:ESP32MD5代码_esp32idfmd5开启-CSDN博客ESP32学习笔记(47)——加密算法AES/MD5/SHA_esp32aes-CSDN博客特此致谢!上一回解析了ESP-IDF中组件(components)中MD5相关的例程,也给出了笔者参照该例程自行编写的计算MD5的代码以......
  • autoware.universe源码略读(3.5)--perception:compare_map_segmentation/crosswalk_tra
    autoware.universe源码略读3.5--perception:compare_map_segmentation/crosswalk_traffic_light_estimatorcompare_map_segmentationcompare_elevation_map_filter_nodedistance_based_compare_map_filter_nodeletvoxel_based_approximate_compare_map_filter_nodeletvox......
  • ESP32驱动TTP224触摸模块控制RGB灯亮灭---MircoPthon
    本文将指导读者如何使用Python编程ESP32微控制器,结合TT224触摸模块,实现对RGBLED灯的智能控制。通过详细的步骤和代码示例,读者可以快速搭建起自己的智能RGB灯控制系统。1.引言ESP32是由乐鑫科技(EspressifSystems)开发的一种为控制器,它具有以下主要特性:       ......