将 ZIP 文件发送到基于 REST 的 API,该 API 使用基于 Flutter 的移动应用程序托管在 AWS 上的 SSL TLS (https)

Posted

技术标签:

【中文标题】将 ZIP 文件发送到基于 REST 的 API,该 API 使用基于 Flutter 的移动应用程序托管在 AWS 上的 SSL TLS (https)【英文标题】:Send ZIP file to a REST based API which is using SSL TLS (https) hosted on AWS from a flutter based mobile application 【发布时间】:2020-07-08 08:32:43 【问题描述】:

之前我创建了一个 REST API,它获取一个 ZIP 文件和其他两个参数作为来自 Flutter 移动应用程序的输入

var uri = Uri.parse("http://XX.XXX.XX.XX/gatewayapp/userinfo/sendFileToServer/");
var request = http.MultipartRequest('POST', uri);
     Map<String, String> headers = 
       "Accept": "application/json"
     ;
     //add headers
     request.headers.addAll(headers);
     request.fields["customerNumber"] = customerNumber;
     request.fields['zippassword'] = password;
   var file=  await http.MultipartFile.fromPath(
         'userDetailsFile',
         filePath
     );
     request.files.add(file);
     
     await request.send().then((streamedResponse) async 
     ....Implemented the business logic on the response which I was getting
     

它按预期工作。

我们在 AWS 服务器上使用 nginx 将 API 从 HTTP 迁移到 HTTPS,并使用 HTTPClient 和 HttpClientRequest 更改了来自移动应用程序的所有 GET 和 POST 调用,它按预期工作。

但是,我们无法在 API 上使用 HTTPClient 和 HttpClientRequest 执行多部分请求。我尝试使用 httpclient 方法,但没有运气。我还尝试了以下链接中给出的内容:

Using HTTPClient on Dart lang github

var uri = Uri.parse("https://XX.XXX.XX.XX/gatewayapp/userinfo/sendFileToServer/");    
HttpClient client = await CommonController.createHttpClient();
HttpClientRequest request = await client.post( uri.toString() , 443, filePath);

谁能帮助我朝着正确的方向前进?任何帮助,将不胜感激! 谢谢

【问题讨论】:

【参考方案1】:

抱歉这么晚才回答问题。

我能够使用 Flutter 提供的 HTTPClient 使用 SSL(部署在 AWS 上的自签名证书)发送 ZIP 文件。

问题

    当我们使用 Open SSL 生成证书并将这些证书添加到 NGINX 配置中以启用 SSL 时。 (它没有 root 权限。)

    我们能够通过在HTTPClientRequest 中添加 SSL 证书来命中第一个 HTTPS 请求,如下面的代码所示。但在随后的 HTTP 请求中出现错误。

    static Future createHttpClient(//Passing the parameters) async  
        SecurityContext securityContext = SecurityContext.defaultContext;
        var certificate = (await 
        rootBundle.load(Constants.HTTPS_CRT_PATH)).buffer.asInt8List();
        var key = (await rootBundle.load(Constants.HTTPS_KEY_PATH)).buffer.asInt8List();
        securityContext.useCertificateChainBytes(certificate);
        securityContext.usePrivateKeyBytes(key);
        HttpClient httpClient = new HttpClient(context: securityContext);
        httpClient.badCertificateCallback =
            ((X509Certificate cert, String host, int port) => true);
        HttpClientRequest request = httpClient.postUrl(Uri.parse(url));
        request.contentLength = json.encode(requestBody).length;
        request.write(json.encode(requestBody));
        HttpClientResponse response = await request.close();
        print("response status code "+response.statusCode.toString());
        return response;
    
    

    每次我们发出 HTTP 请求并收到 Bad SSL Handshake 异常错误时,我们都会添加证书:

    I/flutter ( 9066): HandshakeException: Handshake error in client (OS Error:
    I/flutter ( 9066): CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:354)) 
    

解决问题的步骤

    在系统的/etc/ssl/文件夹中添加证书,因为证书需要root权限。 其次,我们需要在发出第一个 HTTP 请求时使用单例设计模式添加一次证书。 第三,在进行任何 HTTP 调用时,我们只需要使用 HTTP Client 的 Multipart 方法发送请求即可。

我将添加代码示例,以使用单例模式添加证书并进行 HTTP 调用。

【讨论】:

@fcdt 感谢您格式化答案并使其更易于理解。

以上是关于将 ZIP 文件发送到基于 REST 的 API,该 API 使用基于 Flutter 的移动应用程序托管在 AWS 上的 SSL TLS (https)的主要内容,如果未能解决你的问题,请参考以下文章

将 zip 文件从 REST 返回到客户端不弹出文件

在Rest API中,需要构建ZIP并下载到客户端系统

如何测试使用邮递员提供 .zip 文件的 REST API?

使用 REST API 上传到 Azure Blob 存储时,Zip 档案损坏

通过 POST 将 CSV 数据发送到 BigQuery REST API

Rest API 基于令牌的身份验证。基本认证