关于在H5或delphi中使用multipart/form-data上传文件的Rest方法

目录

关于在H5或delphi中使用multipart/form-data上传文件的Rest方法

一、先看官方案例:亚马逊Amazon及微软Azure的CloudAPI云API测试项目

1、主要涉及的单元:

1.1、CloudRefactorUI.pas                //  ${YourDelphiInstallPath}\Samples\Object Pascal\Database\CloudAPI\CloudAPITest\  //:云API测试UI主界面单元文件   

1.1.2、CloudPopulator.pas                   //  ${YourDelphiInstallPath}\Samples\Object Pascal\Database\CloudAPI\CloudAPITest\  //:云API测试单元文件

1.1.3、Data.Cloud.AmazonAPI.pas      //  ${YourDelphiInstallPath}\source\data\cloud  //:delphi云数据之云计算的亚马逊的API翻译为pascal的单元

1.1.4、Data.Cloud.CloudAPI.pas          //  ${YourDelphiInstallPath}\source\data\cloud  //:delphi云数据之云计算的公共单元

2、申请云服务的步骤:

2.1、首先要到云服务商的平台上申请账号Account

2.2、申请云平台提供的服务及其访问参数的描述

扫描二维码关注公众号,回复: 12140770 查看本文章

2.3、申请服务签名Signature

2.4、阅读服务的API访问和代码调用说明

3、准备架构和代码的步骤:

3.1、架构与设计

    3.1.1、获取账号的User ID

以上,有官方代码,自己看!下面我用阿里云通讯短信服务API说明如下(代码部分摘自“高勇三层Rest服务器产品”):

3.2、代码的基本步骤(需要你自己按照云服务提供的云API服务的详细说明,一步一步地去接口实现)

    3.2.1、准备所有API访问公用的资源(变量)

    3.2.2、签名验证:按API要求获取最终所需的签名字符串Signature

    3.2.3、组装服务的Url

    3.2.4、请求服务的Url(Get或Post)、获取响应Response、解析返回结果的JSon或XML数据

二、关于multipart/form-data原理

1、什么是multipart/form-data

2、为什么会有multipart/form-data的出现

3、delphi使用TNetHttp体系时解决Rest应用的代码逻辑:

4、参考网友博文:《深入解析 multipart/form-data》  https://blog.csdn.net/wyn126/article/details/96451357

本博客相关:

喜欢的话,就在下面点个赞、收藏就好了,方便看下次的分享:


关于在H5或delphi中使用multipart/form-data上传文件的Rest方法

一、先看官方案例:亚马逊Amazon及微软Azure的CloudAPI云API测试项目

${YourDelphiInstallPath}\Samples\Object Pascal\Database\CloudAPI\CloudAPITest\CloudAPITest.dproj

1、主要涉及的单元:

1.1、CloudRefactorUI.pas                //  ${YourDelphiInstallPath}\Samples\Object Pascal\Database\CloudAPI\CloudAPITest\  //:云API测试UI主界面单元文件   

1.1.2、CloudPopulator.pas                   //  ${YourDelphiInstallPath}\Samples\Object Pascal\Database\CloudAPI\CloudAPITest\  //:云API测试单元文件

1.1.3、Data.Cloud.AmazonAPI.pas      //  ${YourDelphiInstallPath}\source\data\cloud  //:delphi云数据之云计算的亚马逊的API翻译为pascal的单元

1.1.4、Data.Cloud.CloudAPI.pas          //  ${YourDelphiInstallPath}\source\data\cloud  //:delphi云数据之云计算的公共单元

2、申请云服务的步骤:

2.1、首先要到云服务商的平台上申请账号Account

 2.1.1、获取账号的User ID

 2.1.2、获取账号的AK(账号的Json或XML键值对):Account Key

 2.1.2、获取账号的SK(密码的Json或XML键值对):Secret Key 

2.2、申请云平台提供的服务及其访问参数的描述

 2.2.1、老外好像就叫“Buckets”(tmd的翻译过来叫“水桶”)

2.3、申请服务签名Signature

 2.3.1、获取需要的服务的签名Signature

2.4、阅读服务的API访问和代码调用说明

 2.4.1、API访问和代码调用说明

3、准备架构和代码的步骤:

3.1、架构与设计

    3.1.1、获取账号的User ID

以上,有官方代码,自己看!下面我用阿里云通讯短信服务API说明如下(代码部分摘自“高勇三层Rest服务器产品”):

3.2、代码的基本步骤(需要你自己按照云服务提供的云API服务的详细说明,一步一步地去接口实现)

    3.2.1、准备所有API访问公用的资源(变量)

            3.2.1.1、baseURL:协议SCHEME(http或https多数云服务要求https) + 特殊保留字Typical scheme '://' + 主机(host域名或IP) 

                   比如阿里云通讯baseURL:https://dysmsapi.aliyuncs.com

            3.2.1.2、SortedParams: TArray<string>;:云服务的参数字典键值对数组

                   比如阿里云短信服务的参数字典键值对数组(以下出斜体注释的部分参数,其余的参数,大部分云服务API参数均大致相同):

                    Params := TDictionary<string, string>.Create;

                    Params.Add('AccessKeyId', AccessKeyId);    //:AK(见上面2.1.2的说明)
                    Params.Add('Timestamp', GetTimestamp);    //:时间截(不同云服务商不同云服务对其格式有特殊要求)及获取时间截的函数GetTimestamp
                    Params.Add('Format', 'JSON');    //:请求和响应的数据格式(不同云服务商不同云服务对其数据格式有特殊要求:JSON或XML)
                    Params.Add('SignatureMethod', 'HMAC-SHA1');    //:签名的加密算法(不同云服务商不同云服务对其算法有特殊要求)
                    Params.Add('SignatureNonce', THashMD5.GetHashString(TGUID.NewGuid.ToString));    //:每次使用都不一样的一次性加密签名字符串(不同云服务商不同云服务对其有特殊要求:HashMD5常用)
                    Params.Add('SignatureVersion', '1.0');    //:签名的版本
                    Params.Add('Action', 'SendSms');    //:服务的具体函数
                    Params.Add('Version', '2017-05-25');   //:服务的版本
                    Params.Add('RegionId', 'cn-hangzhou');   //:服务的区域
                    Params.Add('PhoneNumbers', PhoneNumbers);  //:其它该服务特有的必备参数
                    Params.Add('SignName', SignName);   //:申请的服务的签名
                    Params.Add('TemplateCode', TemplateCode);  //:其它该服务特有的必备参数
                    Params.Add('TemplateParam', TemplateParam);  //:其它该服务特有的必备参数
                    Params.Add('OutId', '');   //:输出的参数或JSON数据

                    SortedParams := Params.keys.ToArray;

                    TArray.Sort<string>(SortedParams);

            3.2.1.3、构造待签名的请求查询字符串

                    StringBuilder := TStringBuilder.Create;

                    //......代码略

                    SortedQueryString := StringBuilder.ToString.Substring(1);

            3.2.1.4、对待签名的请求串进行URL编码,去掉或替换特殊URL编码字符

                    TNetEncoding.Url.Encode

    3.2.2、签名验证:按API要求获取最终所需的签名字符串Signature

        签名,云服务器提供你申请,你的客户端代码肯定也就知道,只是需要服务器和客户端双方进行验证,以保证就是申请人(申请机构)在访问自己账号下的云服务

        Signature

    3.2.3、组装服务的Url

        Url := 'https://dysmsapi.aliyuncs.com/?Signature=' + Signature + '&' + SortedQueryString;

    3.2.4、请求服务的Url(Get或Post)、获取响应Response、解析返回结果的JSon或XML数据

      HTTP.ContentType := 'application/x-www-form-urlencoded';   //:  HTTP := TNetHTTPClient.Create(nil);                                                                                             

        //:这个HTTP.ContentType便是本文需要讲述的关于html重要head头信息的重要设置赋值                                                                                                               


      Response := HTTP.Get(Url).ContentAsString(TEncoding.UTF8);
      JsonObj := TJSONObject.ParseJSONValue(Response) as TJSONObject;

二、关于multipart/form-data原理

1、什么是multipart/form-data

        它是HTML 表单中的编码方式 (Enctype) 之一,有三种类型:

        application/x-www-form-urlencoded  ==========》对应delphi中的THTTPClient.Post的参数ASource: TMultipartFormData的Mime的类型:TMultipartFormData.Create或TMultipartFormData.AddField或或TMultipartFormData.AddBytes或TMultipartFormData.AddStream的应用程序二进制

                如果要发送大量的二进制数据(non-ASCII),application/x-www-form-urlencoded 显然是低效的,因为它需要用 3 个字符来表示一个 non-ASCII 的字符。因此,这种情况下,应该使用 “multipart/form-data” 格式。

        multipart/form-data  ==========》对应delphi中的THTTPClient.Post的参数ASource: TMultipartFormData的Mime的类型:TMultipartFormData.AddFile的二进制  

                使用“application / x-www-form-urlencoded”对于发送大量二进制数据或包含非ASCII字符的文本效率低下。“multipart / form-data”应该用于提交包含文件,非ASCII数据和二进制数据的表单。

        text-plain(即:默认的application/x-www-urlencoded)  ==========》对应delphi中的Get附在 url 链接后面的字符串或Post网页Body部分的内容;或head方法发送头部请求。

                默认情况下是 application/x-www-urlencoded,当表单使用 POST 请求时,数据会被以 x-www-urlencoded 方式编码到 Body 中来传送,而如果 GET 请求,则是附在 url 链接后面来发送。GET 请求只支持 ASCII 字符集,因此,如果我们要发送更大字符集的内容,我们应使用 POST 请求。

2、为什么会有multipart/form-data的出现

        HTML提交表单数据:
        默认情况下是 application/x-www-urlencoded,当表单使用 POST 请求时,数据会被以 x-www-urlencoded 方式编码到 Body 中来传送,而如果 GET 请求,则是附在 url 链接后面来发送。GET 请求只支持 ASCII 字符集,因此,如果我们要发送更大字符集的内容,我们应使用 POST 请求。
        如果要发送大量的二进制数据(non-ASCII),application/x-www-form-urlencoded 显然是低效的,因为它需要用 3 个字符来表示一个 non-ASCII 的字符。因此,这种情况下,应该使用 “multipart/form-data” 格式。
        使用“application / x-www-form-urlencoded”对于发送大量二进制数据或包含非ASCII字符的文本效率低下。“multipart / form-data”应该用于提交包含文件,非ASCII数据和二进制数据的表单。

3、delphi使用TNetHttp体系时解决Rest应用的代码逻辑:

        delphi的Rest解决方案:《delphi Restful:客户端实现的四种方式及其比较》:https://blog.csdn.net/pulledup/article/details/104132753

        System.Net.HttpClientComponent.pas  ==========》  HTTP := TNetHTTPClient.Create(nil);  ==========》     

                   关于表单的多个数据对象TMultipartFormData的提交:

                   1、Post表单的多个数据对象
                   function Post(const AURL: string; const ASource: TMultipartFormData; const AResponseContent: TStream = nil;
                              const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;

                   2、Put表单的多个数据对象
                   function Put(const AURL: string; const ASource: TMultipartFormData; const AResponseContent: TStream = nil;
                              const AHeaders: TNetHeaders = nil): IHTTPResponse; overload;  ==========》      IHTTPResponse :  System.Net.HttpClient.pas

        System.Net.HttpClient.pas  ==========》  FHttpClient := THTTPClient.Create;  FHttpClient.OnReceiveData := DoOnReceiveData;   Result := THTTPClient(TURLSchemes.GetURLClientInstance('HTTP'));  ==========》 

        System.Net.URLClient.pas  ==========》  FSchemeClients.TryGetValue(AScheme.ToUpper, LClientClass);  if LClientClass <> nil then    Result := LClientClass.CreateInstance;TURLClient.CreateInstance: TURLClient; TURLClient.SetCustomHeaderValue(const Name, Value: string);

        System.Net.Mime.pas  ==========》

       

                   TMultipartFormData = class (TObject)  //:详见类的Public公开属性和方法

                    TMimeTypes = class (TObject)  //:详见类的Public公开属性和方法  ===========》HTTP.ContentType := 'MimeType的类型值';

                    TAcceptValueListBase<T: TAcceptValueItem, constructor> = class (TObject)  //:详见类的Public公开属性和方法

                    THeaderValueList = class (TObject)  //:详见类的Public公开属性和方法

       

        System.NetConsts.pas  ==========》(常量、错误提示)

//:  uses System.NetConsts;
const
  DefaultUserAgent = 'Embarcadero URI Client/1.0'; // Do not translate

  // Common Header Names
  sUserAgent = 'User-Agent'; // Do not translate
  sAccept = 'Accept'; // Do not translate
  sAcceptCharset = 'Accept-Charset'; // Do not translate
  sAcceptEncoding = 'Accept-Encoding'; // Do not translate
  sAcceptLanguage = 'Accept-Language'; // Do not translate
  sAcceptRanges = 'Accept-Ranges'; // Do not translate
  sContentEncoding = 'Content-Encoding'; // Do not translate
  sContentLanguage = 'Content-Language'; // Do not translate
  sContentLength = 'Content-Length'; // Do not translate
  sContentType = 'Content-Type'; // Do not translate
  sLastModified = 'Last-Modified'; // Do not translate
  sContentDisposition = 'Content-Disposition'; // Do not translate

  sLocation = 'Location'; // Do not translate
  sSetCookie = 'Set-Cookie'; // Do not translate
  sCookie = 'Cookie'; // Do not translate

  sRange = 'Range'; // Do not translate

  sXMethodOverride = 'x-method-override'; // Do not translate

  sWWWAuthenticate  = 'WWW-Authenticate'; // Do not translate
  sProxyAuthenticate  = 'Proxy-Authenticate'; // Do not translate
  sAuthorization = 'Authorization'; // Do not translate
  sProxyAuthorization = 'Proxy-Authorization'; // Do not translat

4、参考网友博文:《深入解析 multipart/form-data》  https://blog.csdn.net/wyn126/article/details/96451357

本博客相关:

        1、《delphi Restful:客户端实现的四种方式及其比较

        2、RAD Studio 10.4.1的TEdgeBrowser与javascript交互-基于Chromium的Edge浏览器控件用法之二

        3、《Delphi Restful之客户端javascript与中间件服务器交互》

喜欢的话,就在下面点个赞、收藏就好了,方便看下次的分享:

猜你喜欢

转载自blog.csdn.net/pulledup/article/details/109902772