Browse Source

#IQRV #comment [Restful] 添加upload的接口

gifur 3 years ago
parent
commit
ed1f1cb2f9

+ 45 - 8
Other/libRestfulFunc/RestfulFunc.h

@@ -22,6 +22,7 @@
 
 #include <string>
 #include <map>
+#include <vector>
 
 /*
 * > 0 : 网站返回的错误码,比如 200,404 等
@@ -52,7 +53,9 @@ enum HttpRequestMethod
     TRCE,
     CONNECT,
     MERGE,
-    PATCH
+    PATCH,
+    UPLOAD,
+    DOWNLOAD
 };
 
 enum HttpStatusCode : int
@@ -88,15 +91,16 @@ struct HttpClientRequestConfig
      * @return : 
      */
     HttpClientRequestConfig(const std::string& uri) 
-        :mMethod(HttpRequestMethod::GET), mUri(uri), mToValidCert(false), mBodyContent(""), mTimeoutSecs(0)
+        :mMethod(HttpRequestMethod::GET), mUri(uri), mToValidCert(false)
+        , mBodyContent(""), mContentType(""), mTimeoutSecs(0)
     {
     }
     HttpClientRequestConfig(HttpRequestMethod method)
-        : mMethod(method), mToValidCert(false), mBodyContent(""), mTimeoutSecs(0)
+        : mMethod(method), mToValidCert(false), mBodyContent(""), mContentType(""), mTimeoutSecs(0)
     {
     }
     HttpClientRequestConfig(HttpRequestMethod method, const std::string& uri) 
-        :mMethod(method), mUri(uri), mToValidCert(false), mBodyContent(""), mTimeoutSecs(0)
+        :mMethod(method), mUri(uri), mToValidCert(false), mBodyContent(""), mContentType(""), mTimeoutSecs(0)
     {
     }
 
@@ -107,19 +111,43 @@ struct HttpClientRequestConfig
     void AppendQuery(const std::string& name, const std::string& value) {
         mQueryPairs[name] = value;
     }
-    void ResetQuery() { mQueryPairs.clear(); }
 
     std::string GetBaseUri() const { return mUri; }
     std::string GetSubUri() const { return mSubUri; }
-    const std::map<std::string, std::string>& GetQueryPairs() const { return mQueryPairs; }
     std::string GetRequestUri() const { return mUri + mSubUri; }
 
+    void ResetQuery() { mQueryPairs.clear(); }
+    const std::map<std::string, std::string>& GetQueryPairs() const { return mQueryPairs; }
+
+    void ClearPararm() { mParams.clear(); }
+    void AddParams(const std::string& name, const std::string& value) {
+        mParams.push_back(std::move(std::pair<std::string, std::string>(name, value)));
+    }
+    void SetDefaultParam(const std::string& value) {
+        AddParams("params", value);
+    }
+
+    void ClearFiles() { mFiles.clear(); }
+    void AddFiles(const std::string& filePath) {
+        mFiles.push_back(std::move(std::pair<std::string, std::string>("file_content", filePath)));
+    }
+    std::pair<std::string, std::string> BuildBodyContent() const;
+
     HttpRequestMethod GetType() const { return mMethod; }
 
     bool NeedValidCert() const { return mToValidCert; }
 
-    void SetJsonBody(const std::string& value) { mBodyContent = value; }
-    virtual std::string GetJsonBody() const { return mBodyContent; }
+    void SetJsonBody(const std::string& value) {
+        SetBodyContent(value, "application/json");
+    }
+
+    void SetBodyContent(const std::string& value, const std::string& type) {
+        mBodyContent = value;
+        mContentType = type;
+    }
+
+    virtual std::string GetBodyContent() const { return mBodyContent; }
+    virtual std::string GetContentType() const { return mContentType; }
 
     void SetTimeout(uint32_t timeoutSecs) { mTimeoutSecs = timeoutSecs; }
     uint32_t GetTimeout() const { return mTimeoutSecs; }
@@ -130,8 +158,11 @@ private:
     std::string mUri;
     std::string mSubUri;
     std::string mBodyContent;
+    std::string mContentType;
 
     std::map<std::string, std::string> mQueryPairs;
+    std::vector<std::pair<std::string, std::string> > mParams;
+    std::vector<std::pair<std::string, std::string> > mFiles;
 
     bool mToValidCert;
     uint32_t mTimeoutSecs;
@@ -143,6 +174,12 @@ struct HttpClientPostTypeRequest : public HttpClientRequestConfig
     HttpClientPostTypeRequest(const std::string& uri) :HttpClientRequestConfig(HttpRequestMethod::POST, uri) {}
 };
 
+struct HttpClientDownloadRequest : public HttpClientRequestConfig
+{
+    HttpClientDownloadRequest(const std::string& uri) :HttpClientRequestConfig(HttpRequestMethod::POST, uri) {}
+
+};
+
 struct HttpClientResponseResult
 {
     int statusCode;

+ 77 - 1
Other/libRestfulFunc/RestfulFuncImpl.cpp

@@ -57,12 +57,35 @@ namespace
         case PATCH:
             return http::methods::PATCH;
             break;
+        case UPLOAD:
+            return http::methods::POST;
+            break;
+        case DOWNLOAD:
+            return http::methods::POST;
+            break;
         default:
             break;
         }
 
         return http::methods::GET;
     }
+
+    void GetFileNameAndType(const std::string& absoluteFilePath, std::string& fileName, std::string& contentType)
+    {
+        size_t pos = absoluteFilePath.find_last_of("/\\");
+        fileName = absoluteFilePath.substr(pos + 1);
+        contentType = "application/octet-stream";
+        pos = fileName.find_last_of(".");
+        if (pos != std::string::npos) {
+            std::string ext = fileName.substr(pos + 1);
+            std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+            if (ext == "jpg" || ext == "jpeg") {
+                contentType = "image/jpeg";
+            } else if (ext == "txt" /*|| ext == "log"*/) {
+                contentType = "text/plain";
+            } 
+        }
+    }
 }
 
 void RestfulClient::Do(const HttpClientRequestConfig& requestConfig, HttpClientResponseResult& result)
@@ -87,7 +110,14 @@ void RestfulClient::Do(const HttpClientRequestConfig& requestConfig, HttpClientR
     request.set_request_uri(urib.to_string());
 
     request.headers().add(header_names::accept, "application/json");
-    request.set_body(requestConfig.GetJsonBody(), "application/json");
+
+    if (requestConfig.GetType() == HttpRequestMethod::UPLOAD) {
+        auto p = requestConfig.BuildBodyContent();
+        std::cout << p.second << std::endl;
+        request.set_body(p.second, std::string("multipart/form-data; boundary=") + p.first);
+    } else {
+        request.set_body(requestConfig.GetBodyContent(), requestConfig.GetBodyContent());
+    }
 
     pplx::task<void> requestTask = client.request(request)
      .then([&result](http_response response) ->pplx::task<json::value> {
@@ -121,3 +151,49 @@ void RestfulClient::Do(const HttpClientRequestConfig& requestConfig, HttpClientR
          result.content = ex.what();
      }
 }
+
+
+std::pair<std::string, std::string> HttpClientRequestConfig::BuildBodyContent() const
+{
+
+    std::stringstream data;
+
+    std::string boundary{};
+    for (int i = 0; i < 50; i++) {
+        boundary += (rand() % 26) + 'A';
+    }
+
+    for (auto& param : mParams) {
+        data << "\r\n--";
+        data << boundary;
+        data << "\r\nContent-Disposition: form-data; name=\"";
+        data << param.first;
+        data << "\"\r\n\r\n";
+        data << param.second;
+    }
+
+    for (auto& file : mFiles) {
+        std::string inputFileName;
+        std::string contentType;
+        GetFileNameAndType(file.second, inputFileName, contentType);
+        std::ifstream inputFile;
+        inputFile.open(file.second, std::ios::binary | std::ios::in);
+        std::string inputFileContent = std::string((std::istreambuf_iterator<char>(inputFile)), (std::istreambuf_iterator<char>()));
+        data << "\r\n--";
+        data << boundary;
+        data << "\r\nContent-Disposition: form-data; name=\"";
+        data << file.first;
+        data << "\"; filename=\"";
+        data << inputFileName;
+        data << "\"\r\nContent-Type: ";
+        data << contentType;
+        data << "\r\n\r\n";
+        data << inputFileContent;
+    }
+
+    data << "\r\n--";
+    data << boundary;
+    data << "--\r\n";
+
+    return { boundary, data.str() };
+}

+ 26 - 0
Other/libRestfulFunc/RestfulUtilty.hpp

@@ -0,0 +1,26 @@
+#ifndef _SP_UTILITY_RESTFUL_HELPER_
+#define _SP_UTILITY_RESTFUL_HELPER_
+
+#include <iostream> 
+#include <string>
+
+using namespace std;
+
+namespace Restful
+{
+
+namespace Utility
+{
+
+static void SplitFilePath(const std::string& absoluteFilePath, std::string& fileName, std::string& fileSuffix)
+{
+    //TODO:
+    string::size_type pos = absoluteFilePath.find_last_of("/\\") + 1;
+    fileName = path.substr(pos, absoluteFilePath.length() - pos);
+
+    fileSuffix = absoluteFilePath.substr(absoluteFilePath.find_last_of('.') + 1);
+}
+}
+
+
+#endif //_SP_UTILITY_RESTFUL_HELPER_

+ 15 - 0
Other/libRestfulFunc/test/testNormlReqAns.cpp

@@ -38,5 +38,20 @@ TEST_CASE("test  api stage post api", "[restful]")
     REQUIRE(!result.content.empty());
 }
 
+TEST_CASE("test  api stage upload api", "[restful]")
+{
+    HttpClientRequestConfig config("http://55.6.78.29:8080");
+    config.SetRequestType(HttpRequestMethod::UPLOAD);
+    config.SetChildUri("/api/upload/file");
+    config.SetDefaultParam("{\"branch_no\":\"755\",\"file_head_custom\":\"\",\"file_name\":\"20220301.log\",\"file_path\":\"/home/rvc/dbg/mod_initiativetransfer/20220301.log\",\"file_type\":\"O\",\"first_file_length\":\"105116\",\"last_file_length\":\"\",\"plan_id\":\"dbg\",\"system_type\":\"L\",\"terminal_no\":\"7555980012\",\"upload_length\":\"0\"}");
+    config.AddFiles("/home/rvc/dbg/mod_initiativetransfer/20220301.log");
+    RestfulClient client = RestfulClient::getInstance();
+    HttpClientResponseResult result;
+    client.Do(config, result);
+    std::cout << result.content << std::endl;
+    REQUIRE(!result.content.empty());
+}
+
+