Delphi 和微软的 Azure 云存储

delphi Restful:客户端实现的四种方式及其比较 delphi Restful:客户端实现的四种方式 摘要: 一、NetHTTP技术体系: TNetHTTPClient; TNetHTTPRequest二、REST技术体系: TRESTClient; TRESTRequest; TRESTResponse; TRESTResponseDataSetAdapter三、Indy技术体系:IdHTTP + IdSSLOpenSS... 阅读详情

Delphi 针对云存储的支持,支持了亚马逊的 AWS 和微软的 Azure,不过经过测试,发现对 Azure 的支持是有问题的。然后俺深入研究了一下如何用 Delphi 的代码去访问 Azure 的 Blob -- Azure的云存储叫做 Blob。

物料准备:

Delphi 10.3 社区版。虚拟机 VittualBox 安装 WIN7。

在调试阶段,可以在自己电脑里面,或者虚拟机里面,安装微软官方的 Azure 模拟器。同时,需要安装微软官方的 Azure Resource Manager 客户端GUI工具,这样方便测试和调试。

模拟器只接受来自 127.0.0.1 的访问。如果模拟器安装在虚拟机里面,而你又要从外面去访问它,则需要做一个端口转发。我在 WIN7 虚拟机里面,采用网上查到的 WINDOWS 的 Netsh 命令为系统增加端口转发的方法,发现命令执行成功,也可以用 netsh 命令查到新增加的端口转发表,但是,转发并没有开启来。用 Netstat 查不到打开了转发端口被打开监听。因此,我自己用 Delphi 写了一个端口转发程序 -- 很简单,现成的控件。

 

模拟器的 Blob 工作在端口 10000 上面。访问它的地址是:127.0.0.1:10000。

 

因为端口转发程序是我自己写的,当然就可以把路过的数据都抓下来保存为文件。这样我可以知道访问成功的情况下,究竟是什么数据;或者访问失败的情况下,究竟是什么数据。这样可以知道我自己的程序发出的请求的具体内容。

 

模拟器只支持 HTTP 而不支持 HTTPS。HTTP 是明文,抓下来,正好可以学习一下访问 Azure 需要发送什么内容。

 

Azure Blob 概念:

Azure Blob 是微软提供的云存储。有三种:Block Blob, Page Blob 和 Table Blob。具体区别可以看微软的官方文档的解释。

假设我要上传很多文件到这个云存储里面,采用 Block Blob。每一个文件,叫做一个 Blob。

在一个 Azure 账户底下,首先要有 Container。作为账户拥有者,你可以创建很多 Container。Container 可以看作是一个存放文件的文件夹。

在一个 Container 底下,还可以创建文件夹。但是,对于 Container 来说,文件夹和文件,不是树形的,而是平板的。

如果将一个 Container 的 public 访问权限打开,则可以通过 http://xxx.xxx.xx/yourContainer/yourFolder/ExampleFile.jpg 的方式,直接用浏览器打开看见。

通过使用 Azure 资源管理器去访问模拟器,并抓数据下来看,发现它访问模拟器的内容是 HTTP 文本。

 

Azure 概念 -- 之访问者的身份验证:

Azure 对访问者的身份验证,有两种模式:

1. Shared Key 模式。其实就是采用【用户账号+用户KEY 的方式】。

2. SAS 模式。

 

Shared Key 模式:

你的账户,如果要开放给别人使用,不推荐使用这个模式。因为这个模式,你要把你的账户KEY给别人。在这个模式下,需要做:

1. 在 HTTP 的头里面,增加一些字段,描述这个请求的一些参数;

2. 按照 Azure 的规矩,构造一些请求字段,构成一个签名字符串,这个签名字符串包括了账户和账户的KEY。然后将这个签名字符串,采用 SHA2 的算法,使用账户KEY作为HASH的参数,做成一个签名HASH串。将这个串放到 HTTP 的头里面的一个名为 authorization 的字段里面。这样,在 HTTP 内容里面,就没有你的 KEY,只有使用这个 KEY 计算HASH的签名串。在 HTTP 传输过程中,这个 KEY 不会出现。

3. 上述签名字符串里面有一个比较关键的字段:时间。关于签名字符串的详细规则,后面再说。

4. 如果你的 HTTP 请求的头里面的字段和签名字符串的字段不一致(比如时间字段),则签名验证无法通过,服务器不响应这个请求。

 

SAS 模式:

你有一个账户,也就是你有这个账户的AccountName和KEY,用这个账户名和KEY在 Azure 资源管理器上创建一个对此账户的连接。在资源管理器里面,鼠标右键点击这个账户的 Blob container,选择下拉菜单里面的 Get shared access signature,创建一个 SAS key。或者别人给你一个他的账户的某个 Container 的 SAS 串。有了这个串,你才有访问这个 Container 的权限。

在 SAS 模式下,不需要去计算和创建签名字符串。直接把 SAS 串,放到请求的 URL 的后面就可以了。这里有个用浏览器访问Azure模拟器的例子 URL:

http://192.168.6.5:801/devstoreaccount1/pcplayer1?restype=blob&comp=list&maxresults=1000&delimiter=%2F&st=2019-02-01T03%3A23%3A00Z&se=2019-02-08T03%3A23%3A00Z&sp=rwdl&sv=2018-03-28&sr=c&sig=3S%2Bk6wPfndLWKVEFW1Ab1Nlrh%2BJFkYXg6SQKS7st%2Bx8%3D

 

通过使用浏览器访问上述 URL,然后抓取这个 HTTP 访问的内容数据,然后在 Delphi 底下,直接使用 TIdTCPClient ,采用 TCP 的方式将 HTTP 的内容部分发送给 Azure 模拟器,然后从 TCP 读取其返回值,测试成功。因此,我们可以根据这个 HTTP 访问的内容文本,通过平凑字符串,然后用 TCP 直接发送字符串的方式,完成一次对 Azure 的 HTTP 的访问。这就是官方文档所谓的 REST 访问。

 

实际操作:

对于一个真实的 Azure Blob 的操作,官方文档说它支持 HTTP 和 HTTPS。实际操作可能包括:list 操作;上传文件的操作。list 的操作是 HTTP 的 GET 命令。上传文件的操作是 HTTP 的 PUT 命令。

对于上传文件来说,构造一个 HTTP 的 PUT 命令,包括一些 HTTP 头的字段,Content-Length 字段是必须的。在 HTTP 头的最后,加多一个空行(回车符和换行符),然后紧跟着是要上传的文件的二进制数据(无需做 BASE64编码或者 MIME 编码)。在这个 HTTP 的 PUT 命令(HTTP 的第一行)的结尾部分,加上 SAS 串(PUT 部分的字符串,其实就是浏览器的 URL,只是不包含 HOST 部分)。

 

Delphi 的方法:

Delphi 提供了一个 TAzureBlobService 类。这个类有很多访问 Azure Blob 的方法。看起来这个类只支持 Shared key 模式,因为没有看到它有 SAS 模式的相关属性。采用这个类去访问模拟器,会报签名错误。实际上是这个类在访问模拟器的时候构造的签名字符串有问题(也许选择它的模拟器模式不会有问题,但它的模拟器模式,它固定访问127.0.0.1,而我是在虚拟机外面运行程序,通过虚拟机里面的端口转发程序去访问模拟器,这样我才可以通过用端口转发程序记录数据的功能看看它到底发送了什么数据)。总之,我使用 TAzureBlobService 去访问模拟器,没有成功过。虽然失败,但模拟器返回的 HTTP RESPONSE 很有意思,它提示了签名字符串应该是什么,如下:

<AuthenticationErrorDetail>The MAC signature found in the HTTP request 'rBeHwZfFQXNXBejxTEHoTsJRAFdGtYP8f9fQbwjvnvo=' is not the same as any computed signature. Server used following string to sign: 'GET

x-ms-date:Wed, 30 Jan 2019 15:12:26 GMT

x-ms-version:2015-02-21

/devstoreaccount1/devstoreaccount1/pcplayer1

comp:list

restype:container

timeout:30'.</AuthenticationErrorDetail>

 

它给出来的这个签名字符串,连 GET 后面跟的换行符的个数,都是正确的(GET 后面有一个换行符,然后又11个空行,也就是还有11个换行符)。直接拿这个签名字符串作为模板,构造自己的签名字符串,唯一需要的就是替换掉里面的时间值,也就是 x-ms-date 字段的值。这个值可以由 TAzureBlobService 里面的计算时间值的代码直接复制过来使用,代码如下:

function TForm1.GetXMsDate: string;

begin

  //function TAzureService.XMsDate: string;

  Result := FormatDateTime('ddd, dd mmm yyyy hh:nn:ss "GMT"',

  TTimeZone.Local.ToUniversalTime(Now),

  TFormatSettings.Create('en-US'));

end;

签名字符串准备好以后,采用以下函数对其计算 HASH:

function TForm1.SignString(const Signkey: TBytes;

const StringToSign: string): string;

var

  B: TBytes;

begin

  //为字符串签名 TCloudSHA256Authentication.SignString

  //这里的 SignKey 就是那个 AccountKey

  //这里需要拿来签名的字符串是 StringToSign,其内容是 HTTP 里面的头。包括时间戳。



  B := THashSHA2.GetHMACAsBytes(StringToSign, Signkey, THashSHA2.TSHA2Version.SHA256);

  Result := TNetEncoding.Base64.EncodeBytesToString(B);

end;

 

上述计算方法,也来自 TAzureBlobService,测试有效。

 

将 TAzureBlobService 访问模拟器的数据抓下来,里面就是 HTTP 的内容,直接拿这个内容作为模板,替换掉里面的时间字段的值,以及签名串,然后用 TIdTCPClient 直接发给模拟器,模拟器返回成功!

 

上述方法是 List 一个 BLob。上传一个文件,也是类似操作。

 

因为 DELPHI 不支持 SAS 模式,因此 SAS 模式需要自己做实验。

 

SAS 模式访问模拟器:

首先,通过组合字符串的方式将 SAS 串加到 URL 后面,然后在浏览器地址栏输入这个 URL 直接访问模拟器,成功。

https://docs.azure.cn/zh-cn/storage/common/storage-dotnet-shared-access-signature-part-1?toc=%2fstorage%2fblobs%2ftoc.json 这篇文章讲了 SAS 模式。

 

先测试 SAS 方式做 BlobList,构造一个 URL:

 

http://192.168.6.5:801/devstoreaccount1/pcplayer1?restype=container&comp=list&maxresults=1000&delimiter=%2F&st=2019-02-01T03%3A23%3A00Z&se=2019-02-08T03%3A23%3A00Z&sp=rwdl&sv=2018-03-28&sr=c&sig=3S%2Bk6wPfndLWKVEFW1Ab1Nlrh%2BJFkYXg6SQKS7st%2Bx8%3D

 

这个 URL,使用了我昨天构造的 SAS KEY,也就是上述 URL 的 【st=2019-02-01T03%3A23%3A00Z&se=2019-02-08T03%3A23%3A00Z&sp=rwdl&sv=2018-03-28&sr=c&sig=3S%2Bk6wPfndLWKVEFW1Ab1Nlrh%2BJFkYXg6SQKS7st%2Bx8%3D】这部分。

 

上述 URL,抓包看,HTTP 内容部分,有 HTPP 的头,以下是抓包到的头:

GET /devstoreaccount1/pcplayer1?restype=container&comp=list&maxresults=1000&delimiter=%2F&st=2019-02-01T03%3A23%3A00Z&se=2019-02-08T03%3A23%3A00Z&sp=rwdl&sv=2018-03-28&sr=c&sig=3S%2Bk6wPfndLWKVEFW1Ab1Nlrh%2BJFkYXg6SQKS7st%2Bx8%3D HTTP/1.1

Host: 192.168.6.5:801

Connection: keep-alive

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

Accept-Encoding: gzip, deflate

Accept-Language: zh-CN,zh;q=0.9

 

采用 TIdTCPClient 直接用 TCP 方式将上述 HTTP 内容发送给模拟器,返回成功!

 

那么,上传文件的,其 HTTP 是 PUT,格式请参考以下代码:

procedure TForm1.PutBlobSAS_TCP;

var

  SL: TStringList;

  S: string;

  B: TBytes;

  FileStream: TFileStream;

begin

  //采用 SAS 模式,构造一个 PUT BLOB

  //本代码测试成功。成功上传了一个图片文件到 Azure 模拟器里面

  SL := TStringList.Create;

  try

    SL.Add('PUT /devstoreaccount1/pcplayer1/picture/cpu.jpg?timeout=30&st=2019-02- 
     01T03%3A23%3A00Z&se=2019-02-08T03%3A23%3A00Z&sp=rwdl&sv=2018-03- 
     28&sr=c&sig=3S%2Bk6wPfndLWKVEFW1Ab1Nlrh%2BJFkYXg6SQKS7st%2Bx8%3D HTTP/1.1');

    SL.Add('Connection: Keep-Alive');

    SL.Add('Content-Type: application/x-www-form-urlencoded');

    //SL.Add('Authorization: SharedKey devstoreaccount1:##SHA'); //采用了 SAS,这一行不能要。否则服务器仍然按照这一行去验证 KEY。

    SL.Add('User-Agent: Embarcadero URI Client/1.0');

    SL.Add('x-ms-blob-type: BlockBlob');

    //SL.Add('x-ms-date: ' + Self.GetXMsDate); //SAS 模式下,这个时间戳看起来不需要。

    SL.Add('x-ms-meta-MyMetaData: pcplayer');

    SL.Add('x-ms-version: 2015-02-21');

    SL.Add('Content-Length: 40490');

    SL.Add('Host: 192.168.6.5:801');

    SL.Add(''); //加多一个空行,表示 HTTP 头结束。



    B := BytesOf(SL.Text); //注意这里是否会丢掉最后一个回车换行符?

    Self.IdTcpDoHttp(B, False); //发送页面头部分

  finally

  SL.Free;

end;

//接着发送文件内容二进制数据部分

  FileStream := TFileStream.Create('D:\tt\cpu.jpg', fmOpenRead);

  try

    SetLength(B, FileStream.Size);

    FileStream.Position := 0;

    FileStream.Read(B[0], FileStream.Size);



    S := Self.IdTcpDoHttp(B, True);

    Memo1.Lines.Add(S);

  finally

    FileStream.Free;

  end;

end;

 

 

其中,http 头部分,直接参考了采用 Shared key 模式的上传页面的 HTTP 头。只是一定要去掉 'Authorization: SharedKey devstoreaccount1:##SHA‘ 这一行。否则 Azure 仍然按照这个 Shared key 方式去验证签名。

另外,之前 Shared key 模式下的 http 头里面必须要有的时间戳字段 'x-ms-date: ' + Self.GetXMsDate’ 也不是必须的。有没关系,没有也不影响上传。

这里和 Shared key 模式不同的地方是,对于身份验证,不需要去构造一个签名字符串然后计算其 HASH 然后放到 HTTP 头里面。只需要在 HTTP GET 的参数的结尾部分放入 SAS 串就可以了。

注意,上述 HTTP 头里面有一个 'x-ms-meta-MyMetaData: pcplayer' 这种客制化的 MetaData,对这个文件的描述。上传成功后,采用 Azure 资源管理器可以看到这个文件,并且它的 MetaData 确实有这个客制化的数据。因此我们可以通过这个方式为这个文件加上很多说明信息。

 

对于真实的 Azure 的上传文件的,最好用 HTTPS。这里我就直接使用 Delphi 自带的 TNetHTTPClient 这个专门用于 HTTP 的控件,将它的 SecretProtocols 属性都选中,这样它就自动支持 HTTPS 了。采用这个控件,让它发送上面那个 URL,当然 HOST 部分要改为真实环境的值。以下是测试成功的代码:

procedure TForm1.Button7Click(Sender: TObject);
var
  AHeaders: TNetHeaders;
  URL: string;
  AResponseContent: TStringStream;
begin
  //采用 NetHttpClient 去访问真实的 Azure;
  AResponseContent := TStringStream.Create;

  URL := 'https://Mystore.blob.core.windows.net/study-test/cpu.jpg?timeout=30&sv=2018-03-28&ss=b&srt=sco&sp=rwdlac&se=2019-03-02T04:45:10Z&st=2019-01-01T20:45:10Z&spr=https&sig=cfYUJSBoi2%2BOZsJLRslSBDvwAafdVYcxrngKXPgaGsI0%3D';
  NetHTTPClient1.CustomHeaders['Content-Type'] := 'application/x-www-form-urlencoded';
  NetHTTPClient1.CustomHeaders['x-ms-blob-type'] := 'BlockBlob';
  NetHTTPClient1.CustomHeaders['x-ms-meta-MyMetaData'] := 'My_test_Data';
  NetHTTPClient1.CustomHeaders['x-ms-version'] := '2015-02-21';
  NetHTTPClient1.CustomHeaders['Content-Length'] := '40490';
  //NetHTTPClient1.CustomHeaders('')

  NetHTTPClient1.Put(URL, 'D:\tt\cpu.jpg', AResponseContent, nil);

  Memo1.Lines.Add(AResponseContent.DataString);
  ShowMessage('PUT 完成!');
end;

 

注意 HTTP 头里面的 Content-Length 的值是 40490,这个是我上传的文件 cpu.jpg 的实际大小。

上述代码,上传一个文件到真实的 Azure 账户里面,而不是模拟器,成功!

 

Azure 总结:

1. Azure 有两种权限验证模式。

1.1. Shared key 模式。使用这个模式,需要自己组装一个签名字符串,然后采用 SHA 对这个签名字符串做 HASH,将这个 HAS 字符串放到 HTTP 头里面。

1.2. SAS 模式。直接将账户拥有者为一个 Container 创建的 SAS 串,放到 HTTP 请求的 URL 的后面就可以了。无需再做其它事情。

 

2. 对 Azure Blob 云存储的访问,是 HTTP 或者 HTTPS。对于 HTTP 或者 HTTPS,完全可以自己构建其内容,采用 TCP 发送给 Azure 然后读回其 HTTP RESPONSE。

2.1. 请求一个 Blob 的 List 等操作,是 HTTP 的 GET 操作;

2.2. 上传一个文件,是 HTTP 的 PUT 操作。上传的文件的二进制数据直接跟在 HTTP 头后面。HTTP 头的后面要有一个空行,隔开上传文件的二进制数据。

 

3. 上传一个 Block Blob 就是上传一个文件。在 HTTP 头里面,还可以增加一些自己定义的头字段,用于描述这个文件,Azure 会记录下这些信息。这个是 Azure 对一个 Blob 的 MetaData 描述信息。

3.1. HTTP 头就是 NAME=VALUE格式的字符串。只不过中间不是【=】等号,而是【:】冒号。

 

结束。

 

GoogleOAuth2Authenticator:Delphi OAuth2 Authenticator组件 GoogleOAuth2Authenticator Delphi OAuth2 Authenticator组件 该组件来自Embarcadero提供的TOAuth2Authenticator。 它扩展到了支持OAuth2的Google实现的Embarcadero组件。 注意事项 提供的代码已针对Windows VCL 32位和VCL 64位进行了测试。 由于代码使用TBrowser组件,因此还需要进行其他开发才能支持FireMonkey和(如果可能)Unix。 用法 以用于自定义组件开发的惯用方式安装组件。 将组件放在表单上,​​以代替Embarcadero提供的常规OAUTH2Authenticator。 确保您正在使用的TRESTClient已连接到OAUTH2AuthenticatorGoogle组件。 为组件提供适当的URL,URI,客户端ID,客户端密钥等。 当您发出R 立即下载

相关推荐

不用标注数据!用SAM 3零成本搞定遥感图像分割:SegEarth-OV3保姆级上手教程

本文介绍了如何利用SAM 3和SegEarth-OV3实现零标注遥感图像分割,提供从环境配置到结果优化的完整教程。通过开放词汇语义分割技术,用户无需标注数据即可快速获得专业级分割结果,适用于光伏板统计、灾害评估等场景。

weixin_30415113的博客 585

Azure Integrator Delphi版

Azure Integrator包括表、队列和Blob等标准Windows Azure结构的实现,使开发人员能够快速轻松地将基于云的数据存储、队列管理、表配置等添加到任何桌面、Web或移动应用程序中。包括将与Windows Azure Services的连接快速添加到应用程序所需的一切,包括:广泛的文档、示例应用程序、集成帮助等。Blob-一个易于使用的组件,可用于创建和管理文本或二进制数据的块Blob。用于访问Windows Azure表、Blob和队列的易于使用的组件。表-创建、更新和删除表和表实体。

q2315702359的博客 543

calibration的“前世今生”——从simulink开发到CANape的XCP标定

整体思路 备注: elf可简单的看作为hex和map的集合,其中包括可执行的程序、变量及其对应的地址(simulink生成代码是也可以勾选生成ASAP2的a2l文件,有变量但变量对应的地址为空,只有编译后才分配地址) 定义变量是观测值还是标定值需要在simulink中的数据字典定义变量存储类型,详见simulink系列。 1. 前期准备A2L的制作 安装完成CanApe软件 , 插上CanApe硬件( 如:vector 1640A)。打开A2L编辑软件 ASAP2 Editor(注意不是ASAP2 Vi

IHTY_NUI的博客 1万+

Delphi XE新的http控件TNetHTTPClient

众所周知,旧版的Delphi里面,自带的http请求控件是indy的http,indy的控件请求https的时候,需要依赖于opensll,并且异步这块并不好.新版的Delphi XE8以上的版本, 推出了TNetHttpClient,TNetHttpClient既可以阻塞(如同INDY),又可以异步(这就很全面了)。TNetHttpClient不再和INDY一样依赖OPENSSL。

AI创世纪的博客 3781

机器学习预测土壤养分:从电导率、pH到随机森林与神经网络的农业实践

在智慧农业与精准农业领域,机器学习已成为处理复杂农业数据、挖掘潜在规律的关键技术。其核心原理在于通过算法从多维数据中自动学习特征与目标变量之间的映射关系,尤其擅长捕捉非线性关联。这项技术的核心价值在于能够将传统上依赖昂贵、耗时实验室分析的问题(如土壤养分检测),转化为基于易获取传感器数据(如电导率、pH值)的快速、低成本预测任务,为农业生产的实时决策与资源优化提供了全新可能。其典型应用场景包括作物生长监测、产量预测以及精准施肥管理等。本文聚焦于利用随机森林和神经网络等回归算法,构建通过土壤物理参数预测氮磷钾

weixin_33693070的博客 665

【Codesys】获取从站信息,判断是否从站断联,总线丢失

获取EtherCAT从站信息,判断是否从站断联,总线丢失

qq_35316470的博客 5731

TNetHttpClient的用法

TNetHttpClient的用法 TNetHttpClient是DELPHI XE8新增加的控件。 在之前,我们一般都是使用IDHTTP控件,但在安卓、IOS等非WINDOWS平台,IDHTTP访问HTTPS却不行了。 大家知道INDY的SSL访问局限于WINDOWS平台,并不支持跨平台HTTPS访问。 鉴于以上原因,所以EMB才推出了TNetHttpClient。 TNetHttpC...

weixin_30302609的博客 3399

【通信协议】I2C总线(一主多从)

I2C总线(一主多从)之软件模拟代码详解

m0_75090944的博客 9840

TNetHTTPClient演示

TNetHTTPClient演示 TNetHTTPClient是DELPHI新增加的异步HTTP通信控件(区别于INDY的阻塞控件)。 unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, V...

weixin_30568591的博客 765

什么是信噪比?信噪比越大好还是越小好?

在进行声音增强的时候,往往需要考虑声音信号和噪声的信噪比,那么信噪比是什么呢?越大越好还是越小越好,此处引入百度百科的解读: 信噪比,英文名称叫做SNR或S/N(SIGNAL-NOISE RATIO),又称为讯噪比。是指一个电子设备或者电子系统中信号与噪声的比例。这里面的信号指的是来自设备外部需要通过这台设备进行处理的电子信号,噪声是指经过该设备后产生的原信号中并不存在的无规则的额外信号(或信息),并且该种信号并不随原信号的变化而变化。 同样是“原信号不存在”还有一种东西叫“失真”,失真和噪声实际上有一

码匀的博客 7万+

kaggle学习笔记-餐厅数据挖掘

分析Zomato数据集的基本思想是为了公平地了解影响在班加罗尔不同地方建立不同类型餐厅的因素,每个餐厅的总评级,班加罗尔是这样一个城市,拥有超过12,000家餐厅,餐厅供应来自世界各地的菜肴。每天都有新的餐馆开业,这个行业还没有饱和,需求也在与日俱增。然而,尽管需求不断增加,新餐馆却很难与老牌餐馆竞争。大多数餐厅都供应同样的食物。班加罗尔是印度的IT之都。这里的大多数人主要依靠餐馆的食物,因为他们没有时间自己做饭。由于对餐馆的需求如此巨大,因此研究一个地方的人口统计学就变得很重要。

优快云XXCQ的博客 1862

Delphi 通过TNetHTTPClient访问http,最新解析快手无水印视频地址链接方法

Delphi 通过TNetHTTPClient访问http,最新解析快手无水印视频地址链接方法

byc6352的专栏 5959

高通SDX12:ProSLIC Si32185移植调试

高通 SDX12 语音芯片slic 音频驱动 Si32185

不秃头的程序猿Gabriel的博客 2037

NetHTTPClient访问https网站出错。

/);在ValidateServerCertificate事件里加这句:beginend;

9807146wang的专栏 483

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

用NetHttpClient执行Post操作遇到的问题

用NetHttpClient执行Post操作遇到的问题 最近在做接口的调试,用NetHttpClient来进行相关操作。部分数据是用get方法来操作的,没有问题,但有个数据是用Post来操作的,始终报错,用了抓包分析工具发现没有发送数据出去。但找不出代码的问题,请大家帮忙看看。 关键部分代码如下: procedure TTabbedwithNavigationForm.Button3Click(Sender: TObject); var joj,jodata:tjsonobject;

976

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

delphi10.2的散列单元hash.pas

这是一个从数据生成MD5哈希值(Hash)的单元,广泛用于加密领域type /// &lt;summary&gt; Hash(哈希/散列)相关异常 &lt;/summary&gt; EHashException = class(Exception); /// &lt;summary&gt; 将通用函数记录到所有哈希函数&lt;/summary&gt; THash = record...

千里独行的专栏 1231

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Delphi开发短信应用-阿里云服务

目录 Delphi开发短信应用-阿里云服务 1.1、入参列表 短信Rest请求参数: 短信输入参数: 1.2、出参列表 1.3、Rest响应错误码列表 1.4、基于Node.js的SDK代码demo参考及说明 二、Delphi实现阿里云短信的关键-签名算法的实现 2.1、第一步:请求参数: 2.2、第二步:根据参数Key排序(顺序): 2.3、第三步:构造待签名的请求串: 2.4、第四步:阿里云专用签名: 2.5、第五步:增加签名结果到请求参数中,发送请求: 三、用Del...

pulledup的博客 1582

Delphi调用腾讯云最新签名方法v3 TC3-HMAC-SHA256发送短信

参考了高文杰先生的代码,结合自己的学习增添了最新TC3-HMAC-SHA256 v3版本的接口。 腾讯云的TC3 v3鉴权比较复杂,当然这是相对于Delphi下而言,其实在Python下直接使用SDK要省事儿的多。本文的源代码就不贴了,需要的可以去原文下载。 一、TC3鉴权单元 为了方便复用,写了一个TC3鉴权单元文件:TC3_Authorization.pas { 2021-02-15 广西南宁 张旭州 腾讯云 TC3-HMAC-SHA256 生成鉴权数据 } unit TC3_Auth..

天狼星专栏 1872

delphi xe3 mysql,delphi10.3安装使用mySQL

这里将告诉您delphi10.3安装使用mySQL,教程操作步骤:1】下载安装好mySQL环境2】FDConnection1的设置3】执行增删改SQL语句和查询Select语句4】客户端连接1】下载安装好mySQL环境,注意32位/64位。本篇为32位mysql32位下载链接: https://pan.baidu.com/s/1hVS_vbBQUAnMakDdlN07ZQ 提取码: wx44MYS...

weixin_42544838的博客 442

RAD Studio Delphi 10.4在Windows,Android,iOS,macOS和Linux上更快地可视化开发APP应用软件及新增功能详解

RAD Studio 10.4的新增功能 RAD Studio 10.4提供了显着增强的高性能本机Windows支持,通过出色的快速代码完成功能提高了生产率,通过托管记录提高了代码速度,并在现代多核CPU上增强了并行任务,提供了1000多个质量和性能增强功能,等等。 Delphi 10.4现在可用 我们很高兴地宣布,RAD Studio 10.4 Sydney现已上市。此版本在整个产品中添加了重要的新功能和增强的Windows功能,此外还跨支持的平台提供了重要的生产力和性能增强功能。任何活跃的Update

Delphi开发局QQ群:32422310 6690

【亲测免费】 Delphi 阿里云对象存储 (OSS) 库:云端存储的强大助力

Delphi 阿里云对象存储 (OSS) 库:云端存储的强大助力 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在当今的云计算时代,云端存储服务已成为开发者和企业不可或缺的一部分。为了帮助 Delphi 开发者更轻松地集成阿里云对象存储(OSS)服务,我们推出了这个专门为 Delphi 设计的阿里云 OSS 库。这个库不仅提供了对阿里云 OSS 核心功能的全面支持,还...

gitblog_09700的博客 1121

用Delphi调用阿里云的OpenAPI更新动态域名解析记录

坑3:获取UTC时间,UTC时间也就是我们说的世界标准时间,正常我们获取UTC时间都是带毫秒的,这个一点问题都没有,而且也都是ISO8601的标准对时间进行格式化,但是我发现,在生成签名值的时候,和官方算出来的虽然一模一样,但是每次还是提示签名值不对,这个坑整整耗了我一天时间,百思不得其解。1、这个也是最最关键的必不可少的一步,就是你家必须要有公网IP,现在很多地方宽带供应商只给内网IP(特别是移动和联通),如果是电信的话,可以打10000号免费开通公网IP功能,至于给不给你开,看各地的政策。

1788

http的首部Headers之Delphi Rest开发http(一)

http的首部Headers之delphi开发TNetHTTPClient所用的TNetHeaders(一) 一、概念 二、TNetHTTPClient的首部定义TNetHeaders var LHTTPClient : TNetHTTPClient; LCustHeaders : TURLHeaders; 2.1、TNetHTTPClient客户端 LHTTPClient := TNetHTTPClient.Create(nil); 2.2、L...

pulledup的博客 5054

使用SAS和JavaScript前端上传Azure Bolb大文件

问题描述: Azure Storage Rest API提供了对于大文件分块上传方法,分别使用Put Block和Put Block List实现相关功能 参考链接: Uploading Large Files in Windows Azure Blob Storage Using Shared Access Signature, HTML, and JavaScript Blo...

dengao9681的博客 691

httpf发送 json_https和http的post发送总结

本文为转贴内容,感谢作者阿进!需要转发数据到客户的https的服务器上出现一系列问题总结如下:1.因为是https首先考虑到用最新的控件NetHTTPClient(只有在XE8以上才有)。2.客户的服务器需要先登录例如:域名/authentication?account=admin&password=001Method: POSTreturn:200:成功404:不存在606:自定义错误...

weixin_39595487的博客 859

Azure云平台学习之路(一)——Azure简介

1、什么是Azure? Microsoft Azure是由微软所发展的一套云计算操作系统(云平台),提供各种优质的服务:计算、存储、数据、网络和应用程序。Azure意为天蓝色、蔚蓝色。 2、Azure特点? (1)平台即服务(Platform as a Service,PaaS)+ 基础架构即服务(Infrastructure as a Service,IaaS)。

李瑞远-时空数据 5327
上一篇: Delphi 安卓 APP 动态权限申请
下一篇: Delphi 10.3 不支持 Android 5
pcplayer
博客等级 码龄26年 633粉丝 284原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值