基于Delphi 7与Chilkat实现智能卡认证并POST PDF文件
问题描述
我正在使用Delphi 7和Chilkat库,尝试通过智能卡认证访问网站并POST上传PDF文件以获取上传索引。我对智能卡、SSL/TLS、证书、REST等编程领域较为陌生,在Chilkat的众多功能中迷失方向,不知该如何实现需求。
以下是我的部分代码,目前卡在POST上传环节:
http := CkHttp_Create(); cert := CkCert_Create(); success := CkCert_LoadFromSmartcard(cert, ''); if (success = False) then begin Memo1.Lines.Add(CkCert__lastErrorText(cert)); Memo1.Lines.Add('Certificate not loaded.'); Exit; end; if (CkCert_HasPrivateKey(cert) <> True) then begin Memo1.Lines.Add('A private key is needed for TLS client authentication.'); Memo1.Lines.Add('This certificate has no private key.'); Exit; end; sock := CkSocket_Create(); success := CkSocket_SetSslClientCert(sock, cert); if (success <> True) then begin Memo1.Lines.Add(CkSocket__lastErrorText(sock)); Exit; end; bTls := True; port := 443; maxWaitMs := 5000; success := CkSocket_Connect(sock, mysite, port, bTls, maxWaitMs); if (success <> True) then begin Memo1.Lines.Add('Connect Failure Error Code: ' + IntToStr(CkSocket_getConnectFailReason(sock))); Memo1.Lines.Add(CkSocket__lastErrorText(sock)); Exit; end; rest := CkRest_Create(); success := CkRest_UseConnection(rest, socket, bAutoReconnect); if (success <> True) then begin Memo1.Lines.Add(CkRest__lastErrorText(rest)); Exit; end;
在此处我需要使用POST方式上传文件。我曾尝试使用httprequest,但因需要智能卡认证而失败。请问该如何解决?
解决方案
不需要绕开已建立的带智能卡认证的连接,直接基于当前的CkRest对象完成文件上传即可。Chilkat的CkRest支持通过已认证连接发送多表单数据POST请求,具体步骤如下:
- 设置POST目标路径:替换为实际的上传接口路径
- 添加要上传的PDF文件:指定接口要求的文件字段名和本地文件路径
- 发送请求并解析响应:调用对应方法发送请求,根据接口返回格式提取上传索引
续接已有代码的实现示例
// 续接你已有的代码,在成功建立rest连接后添加: var response: PWideChar; uploadIndex: string; begin // 替换为实际的上传接口路径,比如'/api/upload' const uploadPath = '/your/upload/api/path'; // 添加要上传的PDF文件,第一个参数是接口要求的文件字段名,第二个是本地文件路径 success := CkRest_AddFileForUpload(rest, 'file', 'C:\path\to\your\file.pdf'); if not success then begin Memo1.Lines.Add(CkRest__lastErrorText(rest)); Exit; end; // 如果接口需要额外表单参数,可添加(示例) // success := CkRest_AddParam(rest, 'description', '业务文档'); // if not success then ... // 发送multipart/form-data格式的POST请求 response := CkRest_FullRequestMultipart(rest, 'POST', uploadPath); if CkRest_getLastMethodSuccess(rest) <> True then begin Memo1.Lines.Add(CkRest__lastErrorText(rest)); Exit; end; // 解析响应获取上传索引(根据接口返回格式调整) // 示例:若返回JSON格式,使用Chilkat的CkJsonObject解析 // var json: HCkJsonObject; // json := CkJsonObject_Create(); // success := CkJsonObject_Load(json, response); // if success then // uploadIndex := CkJsonObject_stringOf(json, 'uploadIndex'); Memo1.Lines.Add('上传响应:' + response); Memo1.Lines.Add('上传索引:' + uploadIndex); // 释放资源(遵循Chilkat内存管理规则) CkHttp_Dispose(http); CkCert_Dispose(cert); CkSocket_Dispose(sock); CkRest_Dispose(rest); end;
简化版实现(直接用CkHttp)
如果不想手动处理Socket连接,也可以直接用CkHttp对象绑定智能卡证书,简化流程:
var http: HCkHttp; cert: HCkCert; success: Boolean; response: PWideChar; begin http := CkHttp_Create(); cert := CkCert_Create(); success := CkCert_LoadFromSmartcard(cert, ''); if not success then begin Memo1.Lines.Add(CkCert__lastErrorText(cert)); Exit; end; // 直接将智能卡证书绑定到Http对象,自动处理TLS客户端认证 success := CkHttp_SetSslClientCert(http, cert); if not success then begin Memo1.Lines.Add(CkHttp__lastErrorText(http)); Exit; end; // 上传文件,参数依次为:接口URL、文件字段名、本地文件路径、可选额外参数名、可选额外参数值 response := CkHttp_PostMultipart(http, 'https://mysite.com/your/upload/api/path', 'file', 'C:\path\to\file.pdf', '', ''); if CkHttp_getLastMethodSuccess(http) <> True then begin Memo1.Lines.Add(CkHttp__lastErrorText(http)); Exit; end; Memo1.Lines.Add('上传响应:' + response); // 释放资源 CkHttp_Dispose(http); CkCert_Dispose(cert); end;
注意事项
- 替换代码中的域名、上传接口路径、文件路径为实际值
- 若接口要求的文件字段名不是
file,需对应修改AddFileForUpload或PostMultipart中的字段名参数 - 解析响应时要根据接口实际返回格式调整,JSON格式用Chilkat的JSON对象处理,纯文本直接提取即可
内容的提问来源于stack exchange,提问作者ralu
相关产品推荐
相关产品推荐

