| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 88 人关注过本帖, 1 人收藏
标题:跟我一起学微信公众平台开发(四)
只看楼主 加入收藏
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1300
注 册:2021-10-13
结帖率:97.14%
收藏(1)
 问题点数:20 回复次数:5 
跟我一起学微信公众平台开发(四)
前一阵子,受困于以form-data格式post方法上传文件的困惑,导致我的微信公众号开发受阻,迟迟没有进展。。。
25号晚上1点多钟,脑子突然灵光一闪,那个问题不费吹灰之力就解决了,之前求助deepseek也没有解决。我把解决方法反哺给deepseek了,以后有同样问题它就可以正确解答了。

今天,微信公众号的素材管理模块的工作总算是完成了(有待完善),赶紧发上来分享给大家,就当是祝大家新年快乐。。。

谈谈开发思路,供感兴趣的狐友参考。

微信的素材管理有7个功能接口,新增临时素材,获取临时素材(这两个没有对我开放权限),新增永久素材,获取永久素材,删除永久素材,获取素材总数, 获取素材列表。因为功能差不多,所以我把他们整合到一个类里面,建立一个自定义类materials,分别用append,get,delete,getcount,getlist方法来实现这几个功能。还有一个uploadimg方法,是用来上传图文信息里的图片的,就是这个玩意让我苦思冥想很久。。。

现在把这个materials类的代码发上来,有感兴趣的,可以私信我要源代码,我的myclass有点大好像不能上传

这里是主要代码:
程序代码:
**************************************************
*-- 类:           materials (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  custom
*-- 基类:    custom
*-- 时间戳:   01/28/25 11:06:06 PM
*
DEFINE CLASS materials AS custom


    *-- 微信素材库api网址
    apiurl = ""
    *-- 上传素材的类型,默认为image。
    type = "image"
    Name = "materials"


    *-- 新增永久素材
    PROCEDURE append
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        *!*    素材的格式大小等要求
        *!*    图片(image): 10M,支持bmp/png/jpeg/jpg/gif格式
        *!*    语音(voice):2M,播放长度不超过60s,mp3/wma/wav/amr格式
        *!*    视频(video):10MB,支持MP4格式
        *!*    缩略图(thumb):64KB,支持JPG格式
        PARAMETERS mediafile
        *!*    如果没有给mediafile参数
        IF PARAMETERS()=0
            DO CASE 
                CASE this.type="image"
                    mediafile=GETFILE("bmp|jpeg|jpg|png|gif")
                CASE this.type="voice"
                    mediafile=GETFILE("mp3|wma|wav|amr")
                CASE this.type="video"
                    mediafile=GETFILE("mp4")
                CASE this.type="thumb"
                    mediafile=GETFILE("jpg")
                OTHERWISE 
                    MESSAGEBOX("微信素材只支持图片、语音、视频和缩略图!",0+16,"请设置正确的素材type!")
                    RETURN 
            ENDCASE 
        ENDIF 
        *!*    检查文件大小并设置mine类型
        opart=NEWOBJECT("part","myclass")
        opart.fieldname="media" &&设定接口字段名为media
        cstr=FILETOSTR(mediafile)
        nlen=LEN(cstr)
        DO CASE 
            CASE this.type="image"
                IF nlen>10*1024*1024 OR nlen=0
                    MESSAGEBOX("文件大小超过 10MB!",0+16,"上传失败!")
                    RELEASE opart
                    RETURN
                ENDIF
                opart.contenttype="image/"+IIF(LOWER(JUSTEXT(mediafile))="jpg","jpeg",LOWER(JUSTEXT(mediafile)))
            CASE this.type="voice"
                IF nlen>2*1024*1024 OR nlen=0
                    MESSAGEBOX("文件大小超过 2MB!",0+16,"上传失败!")
                    RELEASE opart
                    RETURN
                ENDIF
                opart.contenttype="audio/"+ICASE(LOWER(JUSTEXT(mediafile))="mp3","mpeg",LOWER(JUSTEXT(mediafile))="wma","x-ms-wma",LOWER(JUSTEXT(mediafile)))
            CASE this.type="video"
                IF nlen>10*1024*1024 OR nlen=0
                    MESSAGEBOX("文件大小超过 10MB!",0+16,"上传失败!")
                    RELEASE opart
                    RETURN
                ENDIF
                opart.contenttype="video/mp4"    
            CASE this.type="thumb"
                IF nlen>64*1024 OR nlen=0
                    MESSAGEBOX("文件大小超过 64KB!",0+16,"上传失败!")
                    RELEASE opart 
                    RETURN
                ENDIF
                opart.contenttype="image/jpeg" 
            OTHERWISE 
                MESSAGEBOX("微信素材只支持图片、语音、视频和缩略图!",0+16,"请设置正确的素材type!")
                RELEASE oport
                RETURN 
        ENDCASE
        opart.attachment=mediafile

        *!* 准备请求体
        omultipart=NEWOBJECT("multipart","myclass")
        omultipart.parts.add(opart)

        *!* 下面这段逻辑有点问题,没考虑好在什么环境下使用
        IF this.type="video/mp4" &&微信要求上传视频时还要提交视频描述信息,json结构
            opart2=NEWOBJECT("part","myclass")
            opart2.contenttype="application/json"
            opart2.fieldname="description"
            opart2.append("id","description")
        *!*        构建json格式数据,格式如下
        *!*        {
        *!*        "title":VIDEO_TITLE,
        *!*        "introduction":INTRODUCTION
        *!*        }
        *!*    ojson应该在此方法前构建好,这里就当是检查是否遗漏
        *    IF EMPTY(opart2.content)
                ojson=NEWOBJECT("json","myclass")
                ctitle=INPUTBOX("请在文本框中输入您想显示的视频标题!","请提供视频的标题!")
                ojson.add("title",ctitle)
                cdescription=INPUTBOX("请在文本框中输入您想显示的视频描述,越详细越好。","请提供视频的描述!")
                ojson.add("introduction",cdescription)
                opart2.content=ojson.generate()
                RELEASE ojson
        *    ENDIF 
            omultipart.parts.add(opart2)
        ENDIF 
        *!* 
        omultipart.setrequestheader()
        omultipart.setrequestbody()
        lcheader=omultipart.contenttype+omultipart.boundary
        lcbody=CREATEBINARY(omultipart.requestbody)
        STRTOFILE(lcbody,"request_body.txt") && debug,成功后注释掉。
        RELEASE opart,omultipart

        this.apiurl="https://api.weixin./cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",otoken.access_token)
        this.apiurl=STRTRAN(this.apiurl,"TYPE",this.type)

        * 准备发送 HTTP POST 请求
        LOCAL loHTTP, lcResponse
        *loHTTP = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
        lohttp=NEWOBJECT("microsoft.xmlhttp")
        *loHTTP.SetProxy(2, "127.0.0.1:8888")  && 设置代理,方便调试,没问题后可以注释掉
        loHTTP.Open("POST", this.apiurl, .F.)
        *loHTTP.SetRequestHeader("Accept-Encoding","gzip, deflate, br")
        *loHttp.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
        loHTTP.SetRequestHeader("Content-Type", lcHeader)
        *loHTTP.SetRequestHeader("Content-Length", LEN(lcbody))
        loHTTP.Send(lcBody)
        WAIT "数据上传中。。。" WINDOW AT 25,90 TIMEOUT 5
        lcresponse=lohttp.responsetext
        RELEASE lohttp

        * 获得服务器响应文本,调试用,完成后可以注释掉
        STRTOFILE(lcresponse,"response.txt")
        MODIFY FILE response.txt nowait
    ENDPROC


    *-- 删除永久素材
    PROCEDURE delete
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        PARAMETERS media_id
        this.apiurl="https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",otoken.access_token)
        ohttp.open("POST",lcurl,.f.)
        cjson="{"+["]+"media_id"+[": ]+["]+media_id+["]+"}"
        ohttp.send(cjson)
        WAIT "正在连接服务器。。。" WINDOW AT 25,90 TIMEOUT 3
        STRTOFILE(ohttp.responsetext,"response.txt")
        MODIFY FILE response.txt nowait
        RELEASE ohttp
    ENDPROC


    *-- 获取永久素材的总数
    PROCEDURE getcount
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        this.apiurl="https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",otoken.access_token)
        lohttp=NEWOBJECT("microsoft.xmlhttp")
        lohttp.open("GET",this.apiurl,.f.)
        lohttp.send()
        WAIT "发送请求。。。" WINDOW AT 25,90 TIMEOUT 3
        lcresponse=lohttp.responsetext
        RELEASE lohttp

        * 获得服务器响应文本,调试用
        STRTOFILE(lcresponse,"response.txt")
        MODIFY FILE response.txt nowait
        *!*    返回说明

        *!*    {
        *!*      "voice_count":COUNT,
        *!*      "video_count":COUNT,
        *!*      "image_count":COUNT,
        *!*      "news_count":COUNT
        *!*    }
    ENDPROC


    *-- 获取指定类型的素材列表
    PROCEDURE getlist
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        this.apiurl="https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",otoken.access_token)
        ojson=NEWOBJECT("json","myclass")
        ojson.Add("image","type")
        ojson.Add(0,"offset")
        ojson.Add(1,"count")
        cjson=ojson.generate()
        ohttp.open("POST",lcurl,.f.)
        ohttp.send(cjson)
        WAIT "正在连接服务器。。。" WINDOW AT 25,90 TIMEOUT 3
        STRTOFILE(ohttp.responsetext,"response.txt")
        MODIFY FILE response.txt nowait
        RELEASE ojson,ohttp
    ENDPROC


    *-- 获取永久素材
    PROCEDURE get
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        PARAMETERS media_id
        this.apiurl="https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",otoken.access_token)
        ohttp.open("POST",lcurl,.f.)
        cjson="{"+["]+"media_id"+[": ]+["]+media_id+["]+"}"
        ohttp.send(cjson)
        WAIT "正在连接服务器。。。" WINDOW AT 25,90 TIMEOUT 3
        STRTOFILE(ohttp.responsetext,"response.txt")
        MODIFY FILE response.txt nowait
        RELEASE ohttp
    ENDPROC


    *-- 新增临时素材
    PROCEDURE appendtemp
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        this.apiurl="https://api.weixin./cgi-bin/media/upload"
    ENDPROC


    *-- 获取临时素材
    PROCEDURE gettemp
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN
        this.apiurl="https://api.weixin./cgi-bin/media/get"
    ENDPROC


    *-- 新增图文信息内的图片素材
    PROCEDURE uploadimg
        *!*    新增临时素材 http请求方式:POST/FORM,使用https https://api.weixin./cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
        *!*    获取临时素材 http请求方式: GET,https调用 https://api.weixin./cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID
        *!*    新增永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
        *!*    获取永久素材 http请求方式: POST,https协议 https://api.weixin./cgi-bin/material/get_material?access_token=ACCESS_TOKEN
        *!*    删除永久素材 http请求方式: POST https://api.weixin./cgi-bin/material/del_material?access_token=ACCESS_TOKEN
        *!*    获取素材总数 http请求方式: GET https://api.weixin./cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
        *!*    获取素材列表 http请求方式: POST https://api.weixin./cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN

        *!* 上传图文信息内的图片至微信公众号服务器,成功则返回图片的网址。图片仅支持jpg和png格式,不超过1M。
        *!* 使用者拿到图片的网址后应保存在表中,方便日后读取。
        PARAMETERS lcimgpng
        IF PARAMETERS()=0
            lcimgpng=GETFILE("jpg|png")
        ENDIF
        * 检查文件大小及内容
        lnFileSize = LEN(FILETOSTR(lcimgpng))
        IF lnFileSize > 1 * 1024 * 1024 OR lnFileSize=0
            MESSAGEBOX("文件大小超过 1MB!",0+16,"上传失败!")
            RETURN
        ENDIF

        * 准备上传诸元:接口字段名,附件,content-type,生成所需post的二进制数据流lcbody

        opart=NEWOBJECT("part","myclass")
        opart.fieldname="media" &&设定接口字段名为media
        opart.attachment=lcimgpng
        IF JUSTEXT(lcimgpng)="JPG"
            opart.contenttype="image/jpg"
        ENDIF 
        IF JUSTEXT(lcimgpng)="PNG"
            opart.contenttype="image/png"
        ENDIF

        omultipart=NEWOBJECT("multipart","myclass")
        omultipart.parts.add(opart)
        omultipart.setrequestheader()
        omultipart.setrequestbody()
        lcheader=omultipart.contenttype+omultipart.boundary
        lcbody=CREATEBINARY(omultipart.requestbody)
        STRTOFILE(lcbody,"request_body.txt") && debug,成功后注释掉。

        RELEASE opart,omultipart

        lcAccessToken = otoken.access_token && otoken是public对象,用来获得令牌access_token
        this.apiurl="https://api.weixin./cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN"
        this.apiurl=STRTRAN(this.apiurl,"ACCESS_TOKEN",lcaccesstoken)

        * 准备发送 HTTP POST 请求的函数

        LOCAL loHTTP, lcResponse
        *loHTTP = CREATEOBJECT("WinHttp.WinHttpRequest.5.1")
        lohttp=NEWOBJECT("microsoft.xmlhttp")
        *loHTTP.SetProxy(2, "127.0.0.1:8888")  && 设置代理,方便调试,没问题后可以注释掉
        loHTTP.Open("POST", this.apiurl, .F.)
        *loHTTP.SetRequestHeader("Accept-Encoding","gzip, deflate, br")
        *loHttp.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
        loHTTP.SetRequestHeader("Content-Type", lcHeader)
        *loHTTP.SetRequestHeader("Content-Length", LEN(lcbody))
        loHTTP.Send(lcBody)
        WAIT "数据上传中。。。" WINDOW AT 25,90 TIMEOUT 5
        lcresponse=lohttp.responsetext
        RELEASE lohttp

        * 获得服务器响应文本,调试用
        STRTOFILE(lcresponse,"response.txt")
        MODIFY FILE response.txt nowait
    ENDPROC


    PROCEDURE Init
        *this.result=NEWOBJECT("json","myclass")
        *!*    this.AddObject("paras","keyvalue")
        *!*    this.AddObject("result","json")
    ENDPROC


ENDDEFINE
*
*-- EndDefine: materials
**************************************************
搜索更多相关主题的帖子: https 请求 qq com api 
3 天前 23:49
schtg
Rank: 12Rank: 12Rank: 12
来 自:Usa
等 级:贵宾
威 望:67
帖 子:1851
专家分:3600
注 册:2012-2-29
收藏
得分:0 
学习啦,谢谢!
前天 06:57
wcx_cc
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:52
帖 子:405
专家分:1291
注 册:2015-10-2
收藏
得分:0 
非常棒!值得称赞!

[此贴子已经被作者于2025-1-29 12:16编辑过]

前天 12:10
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1300
注 册:2021-10-13
收藏
得分:0 
本文中提及的 json类代码:
程序代码:
**************************************************
*-- 类:           json (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  collection
*-- 基类:    collection
*-- 时间戳:   01/01/25 02:02:00 AM
*
DEFINE CLASS json AS collection


    Height = 23
    Width = 23
    *-- 生成的json脚本
    jsscript = ""
    Name = "json"


    *-- 返回json结构中指定属性的值。
    PROCEDURE getvalue
        PARAMETERS ckey,noccurrence
        LOCAL i,j,nleft,nright,cchar,cvalue,n
        cvalue=""

        IF PARAMETERS()=1
            noccurrence=1
        ENDIF

        n=MAX(AT(["]+ckey+[":],this.jsscript,noccurrence),AT(["]+ckey+[" :],this.jsscript,noccurrence)) &&允许“:”前有个空格,容错
        nleft=n+LEN(ckey)+3
        IF n>0
            *!* 确定指定json属性的值的起始位置
            DO WHILE .t.
                cchar=SUBSTR(this.jsscript,nleft,1)
                IF INLIST(cchar,["],"[","{","0","1","2","3","4","5","6","7","8","9","t","f","n")
                    EXIT 
                ELSE
                    nleft=nleft+1
                    LOOP
                ENDIF 
            ENDDO 
            *!* 
        *!*        DO WHILE .t.
        *!*            cchar=ALLTRIM(SUBSTR(this.jsscript,nleft,1))
        *!*            IF cchar=" " &&空格,冒号后面可能不小心输入了空格,剔除它
        *!*                nleft=nleft+1
        *!*                LOOP
        *!*            ELSE 
        *!*                EXIT
        *!*            ENDIF
        *!*        ENDDO

            IF cchar="[" &&说明是数组
                *!*确定与"["匹配的"]"的位置
                i=0
                DO WHILE .t.
                    i=i+1
                    nright=AT("]",this.jsscript,i)
                    IF nright<nleft
                        LOOP
                    ELSE 
                        cvalue=SUBSTR(this.jsscript,nleft,nright-nleft+1)
                        IF OCCURS("[",cvalue)=OCCURS("]",cvalue)
                            EXIT
                        ELSE
                            LOOP
                        ENDIF
                    ENDIF
                ENDDO
            ELSE &&否则就是普通数值
                *!* 亦有可能是json嵌套,2024/12/22 加入json嵌套解读代码
                *!* 12/31 修改代码,未考虑到多重json嵌套。
                IF cchar="{" &&说明值是一个json结构,然后找出匹配的“}”的位置
                    i=0
                    DO WHILE .t. 
                        i=i+1
                        nright=AT("}",this.jsscript,i)
                        IF nright<nleft
                            LOOP
                        ELSE 
                            cvalue=SUBSTR(this.jsscript,nleft,nright-nleft+1)
                            IF OCCURS("{",cvalue)=OCCURS("}",cvalue)
                                EXIT
                            ELSE 
                                LOOP
                            ENDIF 
                        ENDIF
                    ENDDO 
                    *!* 12/31
                ELSE &&然后才是普通数值
                    cscript=this.jsscript+","
                    j=0
                    DO WHILE .t.
                        j=j+1
                        nright=AT(",",cscript,j)
                        IF nright<nleft
                            LOOP
                        ELSE
                            cvalue=SUBSTR(cscript,nleft,nright-nleft)
                            cvalue=STRTRAN(cvalue,["],"")
                            cvalue=STRTRAN(cvalue,[}],"")
                            cvalue=ALLTRIM(cvalue)
                            *!* 12/28加入,复原可能的“:”“,”
                            cvalue=STRTRAN(cvalue,",",",") &&复原逗号
                            cvalue=STRTRAN(cvalue,":",":") &&复原冒号
                            *!* 12/29加入,复原可能的“[]”“{}”
                            cvalue=STRTRAN(cvalue,"[","[") &&复原左中括号
                            cvalue=STRTRAN(cvalue,"]","]") &&复原右中括号
                            cvalue=STRTRAN(cvalue,"{","{") &&复原左大括号
                            cvalue=STRTRAN(cvalue,"}","}") &&复原右大括号
                            *!*
                            EXIT
                        ENDIF
                    ENDDO
                ENDIF
                *!*
            ENDIF
        ENDIF

        RETURN cvalue
    ENDPROC


    *-- 解析json结构。
    PROCEDURE parse
        LPARAMETERS jsonscript
        *!* 12/28发现bug,当json属性的值里有“:”“,”符号时,解析程序出错
        *!* 解决方案,解析前搜索每对引号对,把这两个字符替换掉,最后再复原。
        LOCAL ckey,cstr,i,ii,j,n,ccontent,ckey,cvalue,atemp,nleft,nright,jsarray,ncount,m
        LOCAL ARRAY atemp[1],jsonarraylist[1]
        jsonscript=STRTRAN(jsonscript,CHR(9),"") &&清除tab键
        jsonscript=STRTRAN(jsonscript,CHR(10),"") &&清除ctrl+enter
        jsonscript=STRTRAN(jsonscript,CHR(13),"") &&清除换行符
        jsonscript=allt(jsonscript) &&清除首尾空格
        *!*    ************最基本的json结构检查************
        IF OCCURS("{",jsonscript)<>OCCURS("}",jsonscript) OR OCCURS("[",jsonscript)<>+OCCURS("]",jsonscript) OR MOD(OCCURS(["],jsonscript),2)<>0
            MESSAGEBOX('{,[" 未成对!')
            RETURN .f.
        ENDIF
        *!* 12/28修改,加入代码完成对“:”(:)“,”(,)字符的判断并替换
        n=OCCURS(["],jsonscript)
        FOR i=1 TO n/2
            ccontent=STREXTRACT(jsonscript,["],["],2*i-1)
            ctemp=ccontent
            *!* 12/28 替换“:”
            ctemp=STRTRAN(ctemp,[:],":")
            *!* 替换“,”
            ctemp=STRTRAN(ctemp,[,],",")
            *!* 12/28
            *!* 12/29*!* 替换“[”
            ctemp=STRTRAN(ctemp,"[","[")
            *!* 替换“]”
            ctemp=STRTRAN(ctemp,"]","]")
            *!* 替换“{”
            ctemp=STRTRAN(ctemp,[{],"{")
            *!* 替换“}”
            ctemp=STRTRAN(ctemp,[}],"}")
            *!* 12/29 *!*
            jsonscript=STRTRAN(jsonscript,ccontent,ctemp)
        ENDFOR
        *!*

        this.jsscript=jsonscript
        *****
        *!* 先检查是不是包含json数组的复合结构
        *!* 提取所有json数组,并以AJSON+编号予以替换,保存于jsonarraylist中
        n=0
        DO WHILE .t. 
            IF OCCURS("[",jsonscript)>0 &&说明json结构里有数组
                DIMENSION jsonarraylist[n+1] &&用以保存json数组的内容
                nleft =AT("[",jsonscript) &&确定第一个 "[" 的位置
                i=0
                *!*  下面这段代码确定与第一个 "[" 匹配的 "]" 的位置
                DO WHILE .t.
                    i=i+1
                    nright=AT("]",jsonscript,i) 
                    ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1)
                    IF OCCURS("[",ccontent)<>OCCURS("]",ccontent)
                        LOOP
                    ELSE 
                        EXIT
                    ENDIF
                ENDDO
                *!*
        *!*            ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1) &&提取json数组的整体内容
                n=n+1
                jsarray="AJSON_"+TRANSFORM(n) &&准备替换掉数组的内容
                jsonscript=STRTRAN(jsonscript,ccontent,jsarray)
                jsonarraylist(n)=ccontent
                LOOP
            ELSE 
                *!* 2024/12.22 漏掉一种可能,没有数组,但是有json嵌套
                IF OCCURS("{",jsonscript)>1
                    DIMENSION jsonarraylist[n+1]
                    nleft=AT("{",jsonscript,2)
                    i=0
                    *!* 12/31 发现bug,没有考虑到多重json嵌套,因此修改下面的代码。
                    *!*  下面这段代码确定与第二个 "{" 匹配的 "}" 的位置
                    DO WHILE .t. 
                        i=i+1
                        nright=AT("}",jsonscript,i)
                        ccontent=SUBSTR(jsonscript,nleft,nright-nleft+1)
                        IF OCCURS("{",ccontent)<>OCCURS("}",ccontent)
                            LOOP
                        ELSE 
                            EXIT
                        ENDIF
                    ENDDO 
                    *!* 12/31
                    n=n+1
                    jsarray="OJSON_"+TRANSFORM(n)
                    jsonscript=STRTRAN(jsonscript,ccontent,jsarray)
                    jsonarraylist(n)=ccontent
                    loop
                ELSE 
                    EXIT
                ENDIF
                *!*
            ENDIF
        ENDDO
        *!* 

        *!* 对替换所有数组后的json结构进行解析
        DIMENSION atemp[1]
        ncount=ALINES(atemp,jsonscript,9,",")
        FOR i=1 TO ncount
            ckey  =ALLTRIM(STREXTRACT(STREXTRACT(atemp[i],"",":"),["],["]))
            cvalue=STREXTRACT(atemp[i],":","")
            cvalue=ALLTRIM(STRTRAN(cvalue,"}",""))
            *!* 12/28加入,复原可能存在的“:”,“,”
            cvalue=STRTRAN(cvalue,",",[,])
            cvalue=STRTRAN(cvalue,":",[:])
            *!* 12/29加入,复原可能存在的“[]”,“{}”
            cvalue=STRTRAN(cvalue,"[","[") &&复原左中括号
            cvalue=STRTRAN(cvalue,"]","]") &&复原右中括号
            cvalue=STRTRAN(cvalue,"{","{") &&复原左大括号
            cvalue=STRTRAN(cvalue,"}","}") &&复原右大括号
            *!*
            *!* 12/29加入对数据类型的分析
            *!*    12/29 发现bug,生成的json值不只是文本,还有其他的数据类型,所以。。。
            *!*    上网查了一下,JSON 值可以是:
            *!*    1,数字(整数或浮点数)
            *!*    2,字符串(在双引号中)
            *!*    3,逻辑值(true 或 false)
            *!*    4,数组(在中括号中)
            *!*    5,对象(在大括号中)
            *!*    6,null
            DO CASE 
                CASE LOWER(cvalue)="true" &&json逻辑值真
                    cvalue=.T.
                CASE LOWER(cvalue)="flase" &&json逻辑值假
                    cvalue=.f.
                CASE LOWER(cvalue)="null" &&json null值
                    cvalue=null
                CASE ISDIGIT(cvalue)=.t. &&首字母是数字,我们就需要判断cvalue是否为json的数值型数据
                    IF OCCURS(".",cvalue)<2 &&如果数字字符串里有超过2个“.”,说明不是数字,比如网址
                        *!* 比循环更简便的算法
                        ctemp=cvalue
                        ctemp=CHRTRAN(cvalue,"0123456789.","") &&替换掉所有数字字符和小数点
                        IF LEN(ctemp)=0 &&说明是数字,并没有其他字符
                            noldset=SET("Decimals")
                            ndotpos=AT(".",cvalue)
                            IF ndotpos=0 
                                SET DECIMALS TO ndotpos
                            ELSE 
                                SET DECIMALS TO len(cvalue)-ndotpos
                            ENDIF
                            cvalue=VAL(cvalue)
                            SET DECIMALS TO noldset
                        ENDIF
                    *!*
                    ENDIF
            ENDCASE 
            *!*
            this.Add(cvalue,ckey)
        ENDFOR
        *!*

        *!*    *!* 如果是复合结构,则复原json数组内容
        *!*    IF VARTYPE(jsonarraylist)!="U"
        *!*        FOR i=1 TO ALEN(jsonarraylist)
        *!*            cvalue="AJSON_"+TRANSFORM(i)
        *!*            FOR j=1 TO this.count
        *!*                IF TRANSFORM(this.Item(j))=cvalue
        *!*                    ckey=this.GetKey(j)
        *!*                    this.Remove(ckey)
        *!*                    this.add(jsonarraylist[i],ckey)
        *!*                ENDIF
        *!*            ENDFOR

        *!*        ENDFOR 
        *!*    ENDIF
        *!*    *!*
        *!* 如果是复合结构,则复原json数组内容
        *IF VARTYPE(jsonarraylist)!="U"
        IF VARTYPE(jsonarraylist)!="L"
            FOR i=1 TO ALEN(jsonarraylist)
                cvalue="AJSON_"+TRANSFORM(i)
                m=this.count
                FOR j=1 TO m
                    IF TRANSFORM(this.Item(j))=cvalue
                        ckey=this.GetKey(j)
                        this.Remove(ckey)
                        &ckey=NEWOBJECT([jsonarray],[myclass])
                        &ckey..name=ckey
                        &ckey..parse(jsonarraylist[i])
                        IF j=m
                            this.add(&ckey,ckey)
                        ELSE 
                            this.Add(&ckey,ckey,j)
                        ENDIF
                    ENDIF
                ENDFOR
            ENDFOR 

            FOR i=1 TO ALEN(jsonarraylist)
                cvalue="OJSON_"+TRANSFORM(i)
                m=this.count
                FOR j=1 TO m
                    IF TRANSFORM(this.Item(j))=cvalue
                        ckey=this.GetKey(j)
                        this.Remove(ckey)
                        &ckey=NEWOBJECT([json],[myclass])
                        &ckey..name=ckey
                        &ckey..parse(jsonarraylist[i])
                        IF j=m
                            this.add(&ckey,ckey)
                        ELSE 
                            this.Add(&ckey,ckey,j)
                        ENDIF
                    ENDIF
                ENDFOR
            ENDFOR 

        ENDIF
        *!*
    ENDPROC


    *-- 生成json脚本
    PROCEDURE generate
        *!*    12/29 发现bug,生成的json值不只是文本,还有其他的数据类型,所以。。。
        *!*    上网查了一下,JSON 值可以是:
        *!*    1,数字(整数或浮点数)
        *!*    2,字符串(在双引号中)
        *!*    3,逻辑值(true 或 false)
        *!*    4,数组(在中括号中)
        *!*    5,对象(在大括号中)
        *!*    6,null

        LOCAL cscript,ckey,cvalue,oref,i
        cscript=""
        IF this.Count>0
            FOR i=1 TO this.Count
                ckey=this.GetKey(i)
                IF VARTYPE(this.Item(i))="O"
                    oref=this.Item(i)
                    cvalue=oref.generate()
                ELSE
                    cvalue=this.Item(i)
                ENDIF
                *!* 12/29加入对值的类型判断
                DO CASE 
                    CASE VARTYPE(cvalue)="N" && 如果该值是数字
                        cscript=cscript+["]+ckey+[":]+TRANSFORM(cvalue)+","
                    CASE VARTYPE(cvalue)="L" && 如果该值是逻辑值
                        cscript=cscript+["]+ckey+[":]+IIF(cvalue=.t.,"true","flase")+","
                    CASE VARTYPE(cvalue)="X" && 如果该值是null
                        cscript=cscript+["]+ckey+[":]+"null"+","
                    OTHERWISE 
                        cscript=cscript+["]+ckey+[":]+IIF(INLIST(LEFT(TRANSFORM(cvalue),1),"[",[{]),TRANSFORM(cvalue),;
                                                        IIF(LEFT(TRANSFORM(cvalue),1)=["],TRANSFORM(cvalue),["]+TRANSFORM(cvalue)+["]))+","
                ENDCASE
                *!*
            ENDFOR 
            cscript=[{]+SUBSTR(cscript,1,LEN(cscript)-1)+[}]
        ENDIF
        this.jsscript=cscript
        RETURN this.jsscript
    ENDPROC


ENDDEFINE
*
*-- EndDefine: json
**************************************************

前天 12:54
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1300
注 册:2021-10-13
收藏
得分:0 
本文中提及的part类,代码如下:
程序代码:
**************************************************
*-- 类:           part (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  keyvalue (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 基类:    custom
*-- 时间戳:   01/25/25 07:04:07 PM
*
DEFINE CLASS part AS keyvalue


    *-- multipart 结构part内容,可以是文字,二进制流,或是json字符串
    content = ""
    *-- 如需附件则指定文件名和路径。
    attachment = ""
    *-- 指定part的内容类型
    contenttype = "text/plain"
    *-- form-data的字段名
    fieldname = "file"
    Name = "part"


    PROCEDURE tostring
        *!*    --example-part-boundary
        *!*    Content-Disposition: form-data; name="avatar"; filename="my_avatar.jpeg"
        *!*    Content-Type: image/jpeg

        *!*    <binary-image data>
        #define CRLF CHR(13)+CHR(10)
        this.append("Content-Type",this.contenttype)
        *!*    cfile=GETFILE("jpg|png|bmp|gif|ico")
        IF FILE(this.attachment) &&如果文件存在
            this.content=FILETOSTR(this.attachment)
            this.fieldname="media"
            this.append("name",this.fieldname)
            this.append("filename",JUSTFNAME(this.attachment))
            this.append("filelength",LEN(this.content))
        ELSE 
        *!*        IF "text" $ this.contenttype
        *!*            this.append("charset","UTF-8")
        *!*        ENDIF 
            this.append("name",this.fieldname)
        ENDIF 

        cstr=this.getkey(1)+": "+this.item(1)+"; "
        ctemp=""
        FOR i=3 TO this.count
            ctemp=ctemp+this.getkey(i)+"="+IIF(VARTYPE(this.item(i))="N",TRANSFORM(this.item(i)),["]+this.item(i)+["])+";"
        ENDFOR 
        cstr=cstr+SUBSTR(ctemp,1,LEN(ctemp)-1)+CRLF
        cstr=cstr+IIF(this.contenttype="text/plain",this.getkey(2)+": "+this.item(2)+"; charset=UTF-8",this.getkey(2)+": "+this.item(2))+CRLF
        cstr=cstr+CRLF+this.content+CRLF
        #unde CRLF
        RETURN cstr
    ENDPROC


    PROCEDURE Init
        *!*    # 请求头 - 这个是必须的,需要指定Content-Type为multipart/form-data,指定唯一边界值
        *!*    Content-Type: multipart/form-data; boundary=${Boundary}
        *!*     
        *!*    # 请求体
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of file"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of pdf file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="key"
        *!*    Content-Type: text/plain;charset=UTF-8
        *!*     
        *!*    text encoded in UTF-8
        *!*    --${Boundary}--

        this.append("Content-Disposition","form-data")
    ENDPROC


ENDDEFINE
*
*-- EndDefine: part
**************************************************



这是派生于键值对keyvalue的一个类,类代码如下:

程序代码:
**************************************************
*-- 类:           keyvalue (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  custom
*-- 基类:    custom
*-- 时间戳:   01/07/25 11:42:10 PM
*
DEFINE CLASS keyvalue AS custom


    *-- 包含参数对的数量
    count = 0
    Name = "keyvalue"

    *-- 保存参数对数组
    DIMENSION array[1,2]


    *-- 添加参数对
    PROCEDURE append
        PARAMETERS ckey,cvalue

        IF this.count=0
            this.array[1,1]=ckey
            this.array[1,2]=cvalue
            this.count=this.count+1
        ELSE 
            IF ASCAN(this.array,ckey,1,this.count,1,9)>0
                this.set(ckey,cvalue)
            ELSE 
                DIMENSION this.array[this.count+1,2]
                this.array[this.count+1,1]=ckey
                this.array[this.count+1,2]=cvalue
                this.count=this.count+1
            ENDIF
        ENDIF 
    ENDPROC


    *-- 删除参数对
    PROCEDURE delete
        PARAMETERS ckey

        nrow=ASCAN(this.array,ckey,1,this.count,1,9)
        IF npos>0
            IF this.count>1
                ADEL(this.array,nrow)
                DIMENSION this.array(this.count-1,2)
            ELSE
                STORE .f. TO this.array
            ENDIF
            this.count=this.count-1
            RETURN .t.
        ENDIF

        RETURN .f.
    ENDPROC


    *-- 设置指定参数的值
    PROCEDURE set
        PARAMETERS ckey,cvalue
        nrow=ASCAN(this.array,ckey,1,this.count,1,9)
        IF nrow>0
            this.array[nrow,2]=cvalue
        ENDIF

    ENDPROC


    *-- 访问参数成员的值
    PROCEDURE item
        LPARAMETERS eIndex

        DO CASE 
            CASE VARTYPE(eindex)="N"
                IF eindex<=this.count AND eindex>0
                    RETURN this.array[eindex,2]
                ENDIF
            OTHERWISE 
                nrow=ASCAN(this.array,eindex,1,this.count,1,9)
                IF nrow>0
                    RETURN this.array[nrow,2]
                ENDIF     
        ENDCASE 

        RETURN ""
    ENDPROC


    *-- 返回键值
    PROCEDURE getkey
        LPARAMETERS nIndex
        IF nindex<=this.count
            RETURN this.array[nindex,1]
        ENDIF 

    ENDPROC


    *-- 生成参数值对字符串
    PROCEDURE tostring
    ENDPROC


ENDDEFINE
*
*-- EndDefine: keyvalue
**************************************************



前天 13:07
sam_jiang
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:852
专家分:1300
注 册:2021-10-13
收藏
得分:0 
本文中提及的multipart类,代码如下:
程序代码:
**************************************************
*-- 类:           multipart (d:\my documents\visual foxpro 项目\myclass.vcx)
*-- 父类:  custom
*-- 基类:    custom
*-- 时间戳:   01/25/25 05:18:03 PM
*
DEFINE CLASS multipart AS custom


    *-- multipart分割符
    boundary = "-----_designed_by_Sam_Jiang"
    *-- multipart的请求头
    requestheader = ""
    *-- multipart请求体
    requestbody = ""
    *-- 指定multipart内容类型
    contenttype = multipart/form-data; boundary= ""
    Name = "multipart"


    *-- 设置请求头
    PROCEDURE setrequestheader
        *!*    # 请求头 - 这个是必须的,需要指定Content-Type为multipart/form-data,指定唯一边界值
        *!*    Content-Type: multipart/form-data; boundary=${Boundary}
        *!*     
        *!*    # 请求体
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of file"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of pdf file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="key"
        *!*    Content-Type: text/plain;charset=UTF-8
        *!*     
        *!*    text encoded in UTF-8
        *!*    --${Boundary}--
        *!*    post 格式 multipart/form-data 和application/x-www-form-urlencoded
        #define CRLF CHR(13)+CHR(10)
        this.requestheader="content-type: "+ this.contenttype+this.boundary+CRLF
        #unde CRLF
    ENDPROC


    *-- 生成请求体文本
    PROCEDURE setrequestbody
        *!*    # 请求体
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of file"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of pdf file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="key"
        *!*    Content-Type: text/plain;charset=UTF-8
        *!*     
        *!*    text encoded in UTF-8
        *!*    --${Boundary}--
        IF this.parts.count=0
            ?CHR(7) &&发声出错提醒
            RETURN .f.
        ENDIF
        #DEFINE CRLF CHR(13)+CHR(10)
        cstrbody="--"+this.boundary+CRLF
        FOR i=1 TO this.parts.count
            omember=this.parts.item(i)
            cstrbody=cstrbody+omember.tostring()
            cstrbody=cstrbody+"--"+this.boundary+CRLF
        ENDFOR 
        THIS.REquestbody=SUBSTR(cstrbody,1,LEN(cstrbody)-2)+"--"+CRLF
        #UNDEF CRLF 
    ENDPROC


    PROCEDURE Init
        *!*    # 请求头 - 这个是必须的,需要指定Content-Type为multipart/form-data,指定唯一边界值
        *!*    Content-Type: multipart/form-data; boundary=${Boundary}
        *!*     
        *!*    # 请求体
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of file"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="name of pdf"; filename="pdf-file.pdf"
        *!*    Content-Type: application/octet-stream
        *!*     
        *!*    bytes of pdf file
        *!*    --${Boundary}
        *!*    Content-Disposition: form-data; name="key"
        *!*    Content-Type: text/plain;charset=UTF-8
        *!*     
        *!*    text encoded in UTF-8
        *!*    --${Boundary}--
        this.AddObject("parts","collection")
    ENDPROC


ENDDEFINE
*
*-- EndDefine: multipart
**************************************************

前天 13:13
快速回复:跟我一起学微信公众平台开发(四)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.139572 second(s), 8 queries.
Copyright©2004-2025, BCCN.NET, All Rights Reserved