|
44 | 44 | }
|
45 | 45 | }
|
46 | 46 |
|
47 |
| - public string invokeAPI(string host, string path, string method, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams) { |
| 47 | + public string invokeAPI(string host, string path, string method, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams) |
| 48 | + { |
| 49 | + return invokeAPIInternal(host, path, method, false, queryParams, body, headerParams, formParams) as string; |
| 50 | + } |
| 51 | + |
| 52 | + public byte[] invokeBinaryAPI(string host, string path, string method, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams) |
| 53 | + { |
| 54 | + return invokeAPIInternal(host, path, method, true, queryParams, body, headerParams, formParams) as byte[]; |
| 55 | + } |
| 56 | + |
| 57 | + private object invokeAPIInternal(string host, string path, string method, bool binaryResponse, Dictionary<String, String> queryParams, object body, Dictionary<String, String> headerParams, Dictionary<String, object> formParams) { |
48 | 58 | var b = new StringBuilder();
|
49 | 59 |
|
50 | 60 | foreach (var queryParamItem in queryParams)
|
|
60 | 70 | host = host.EndsWith("/") ? host.Substring(0, host.Length - 1) : host;
|
61 | 71 |
|
62 | 72 | var client = WebRequest.Create(host + path + querystring);
|
63 |
| - client.ContentType = "application/json"; |
64 | 73 | client.Method = method;
|
65 | 74 |
|
| 75 | + byte[] formData = null; |
| 76 | + if (formParams.Count > 0) |
| 77 | + { |
| 78 | + string formDataBoundary = String.Format("----------{0:N}", Guid.NewGuid()); |
| 79 | + client.ContentType = "multipart/form-data; boundary=" + formDataBoundary; |
| 80 | + formData = GetMultipartFormData(formParams, formDataBoundary); |
| 81 | + client.ContentLength = formData.Length; |
| 82 | + } |
| 83 | + else |
| 84 | + { |
| 85 | + client.ContentType = "application/json"; |
| 86 | + } |
| 87 | + |
66 | 88 | foreach (var headerParamsItem in headerParams)
|
67 | 89 | {
|
68 | 90 | client.Headers.Add(headerParamsItem.Key, headerParamsItem.Value);
|
|
79 | 101 | case "POST":
|
80 | 102 | case "PUT":
|
81 | 103 | case "DELETE":
|
82 |
| - var swRequestWriter = new StreamWriter(client.GetRequestStream()); |
83 |
| - swRequestWriter.Write(serialize(body)); |
84 |
| - swRequestWriter.Close(); |
| 104 | + using (Stream requestStream = client.GetRequestStream()) |
| 105 | + { |
| 106 | + if (formData != null) |
| 107 | + { |
| 108 | + requestStream.Write(formData, 0, formData.Length); |
| 109 | + } |
| 110 | + |
| 111 | + var swRequestWriter = new StreamWriter(requestStream); |
| 112 | + swRequestWriter.Write(serialize(body)); |
| 113 | + swRequestWriter.Close(); |
| 114 | + } |
85 | 115 | break;
|
86 | 116 | default:
|
87 | 117 | throw new ApiException(500, "unknown method type " + method);
|
|
96 | 126 | throw new ApiException((int)webResponse.StatusCode, webResponse.StatusDescription);
|
97 | 127 | }
|
98 | 128 |
|
99 |
| - var responseReader = new StreamReader(webResponse.GetResponseStream()); |
100 |
| - var responseData = responseReader.ReadToEnd(); |
101 |
| - responseReader.Close(); |
102 |
| - return responseData; |
| 129 | + if (binaryResponse) |
| 130 | + { |
| 131 | + using (var memoryStream = new MemoryStream()) |
| 132 | + { |
| 133 | + webResponse.GetResponseStream().CopyTo(memoryStream); |
| 134 | + return memoryStream.ToArray(); |
| 135 | + } |
| 136 | + } |
| 137 | + else |
| 138 | + { |
| 139 | + using (var responseReader = new StreamReader(webResponse.GetResponseStream())) |
| 140 | + { |
| 141 | + var responseData = responseReader.ReadToEnd(); |
| 142 | + return responseData; |
| 143 | + } |
| 144 | + } |
103 | 145 | }
|
104 | 146 | catch(WebException ex)
|
105 | 147 | {
|
|
113 | 155 | throw new ApiException(statusCode, ex.Message);
|
114 | 156 | }
|
115 | 157 | }
|
| 158 | + |
| 159 | + private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary) |
| 160 | + { |
| 161 | + Stream formDataStream = new System.IO.MemoryStream(); |
| 162 | + bool needsCLRF = false; |
| 163 | +
|
| 164 | + foreach (var param in postParameters) |
| 165 | + { |
| 166 | + // Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added. |
| 167 | + // Skip it on the first parameter, add it to subsequent parameters. |
| 168 | + if (needsCLRF) |
| 169 | + formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n")); |
| 170 | +
|
| 171 | + needsCLRF = true; |
| 172 | +
|
| 173 | + if (param.Value is byte[]) |
| 174 | + { |
| 175 | + string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n", |
| 176 | + boundary, |
| 177 | + param.Key, |
| 178 | + "application/octet-stream"); |
| 179 | + formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); |
| 180 | +
|
| 181 | + // Write the file data directly to the Stream, rather than serializing it to a string. |
| 182 | + formDataStream.Write((param.Value as byte[]), 0, (param.Value as byte[]).Length); |
| 183 | + } |
| 184 | + else |
| 185 | + { |
| 186 | + string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", |
| 187 | + boundary, |
| 188 | + param.Key, |
| 189 | + param.Value); |
| 190 | + formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData)); |
| 191 | + } |
| 192 | + } |
| 193 | + |
| 194 | + // Add the end of the request. Start with a newline |
| 195 | + string footer = "\r\n--" + boundary + "--\r\n"; |
| 196 | + formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer)); |
| 197 | + |
| 198 | + // Dump the Stream into a byte[] |
| 199 | + formDataStream.Position = 0; |
| 200 | + byte[] formData = new byte[formDataStream.Length]; |
| 201 | + formDataStream.Read(formData, 0, formData.Length); |
| 202 | + formDataStream.Close(); |
| 203 | + |
| 204 | + return formData; |
| 205 | + } |
116 | 206 | }
|
117 | 207 | }
|
0 commit comments