Closed kyugoa closed 1 year ago
I have the same problem!
my first code, was very simple and naive. unfortunately it did not work as i expected:
// Create RestClient
RestClient client = new RestClient("https://api-server");
// Create RestRequest
RestRequest request = new RestRequest("path", Method.POST) {FormBoundary = "MySpecialBounderyIdentifierTest123"};
request.AddJsonBody(myJsonData);
request.AddFile(filename, fileContent, filename);
// overwrite Content-Type with my custom requirement
request.AddOrUpdateHeader("Content-Type", "multipart/mixed");
// Execute the request
IRestResponse response = client.Execute(request);
// Handle the response
if (response.IsSuccessful)
{
Console.WriteLine("File uploaded successfully!");
}
else
{
Console.WriteLine("File upload failed. Error: " + response.ErrorMessage);
}
output with Version 110.2.0 is:
Authorization: Basic myloginauthkey
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
User-Agent: RestSharp/110.2.0.0
Content-Type: multipart/mixed;
boundary="MySpecialBounderyIdentifierTest123"
Host: api-server
Content-Length: 123
Connection: Keep-Alive
--MySpecialBounderyIdentifierTest123
Content-Type: application/zip
Content-Disposition: form-data; name="mytest.zip"; filename="mytest.zip"
...binary-bytes...
--MySpecialBounderyIdentifierTest123
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="application/json"
{"meta": [{"title": "My Homework","author": {"name": "Tessa","adress": null},"created": 1550743894373}]}
--MySpecialBounderyIdentifierTest123--
my expected output was:
Authorization: Basic myloginauthkey
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
User-Agent: RestSharp/110.2.0.0
Content-Type: multipart/mixed; boundary="MySpecialBounderyIdentifierTest123"
Host: api-server
Content-Length: 123
Connection: Keep-Alive
--MySpecialBounderyIdentifierTest123
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="application/json"
{"meta": [{"title": "My Homework","author": {"name": "Tessa","adress": null},"created": 1550743894373}]}
--MySpecialBounderyIdentifierTest123
Content-Type: application/zip
Content-Disposition: form-data; name="mytest.zip"; filename="mytest.zip"
...binary-bytes...
--MySpecialBounderyIdentifierTest123--
Here is my ugly code to set the order manually. It would be so great if the output of the parameters were in the same order as the executing Add-Methods, or at least some simple functionality to set the order, e.g. an order parameter.
using System.Text;
using System.Linq;
class Program
{
static void Main(string[] args)
{
// Create RestClient
RestClient client = new RestClient("https://api-server");
// Create RestRequest
RestRequest request = new RestRequest("path", Method.POST);
string boundary = "MySpecialBounderyIdentifierTest123";
string filename = "mytest.zip";
// set manually content and encode all data to bytes
byte[] start = Encoding.UTF8.GetBytes($"--{boundary}{Environment.NewLine}");
byte[] separator = Encoding.UTF8.GetBytes($"{Environment.NewLine}{boundary}--{Environment.NewLine}");
byte[] end = Encoding.UTF8.GetBytes($"{Environment.NewLine}--{boundary}--{Environment.NewLine}");
string json = @"{
""meta"": [{
""title"": ""My Homework"",
""author"":
{
""name"": ""Tessa"",
""adress"": null
},
""created"": 1550743894373
}]
}";
// Content-Disposition is optional and not necessary for me/the api-server
byte[] jsonMeta = Encoding.UTF8.GetBytes($"Content-Type: application/json{Environment.NewLine}{Environment.NewLine}{json}");
byte[] fileMeta = Encoding.UTF8.GetBytes($"Content-Type: application/zip{Environment.NewLine}Content-Disposition: form-data; name=\"file\"; filename=\"{filename}\"{Environment.NewLine}{Environment.NewLine}");
// use Linqs byte-concatenation
IEnumerable<byte> requestBytes;
// Combine first json data, then file content! the order is very important.
requestBytes = start // start with boundary-start-sequence
.Concat(jsonMeta) // important: json Data MUST be in the first position, before binary file payload
.Concat(separator) // add boundary separator
.Concat(fileMeta) // file data need as second parameter, after json data!
.Concat(File.ReadAllBytes(filename)) // add file binary payload data as bytes
.Concat(end) // add boundary-endsequence
;
// in my personal case, I have to set an additional custom Content-Type Header
// multipart/form-data does not work with my particular api-server!
string header = $"multipart/mixin; boundary={boundary}";
// set manually header and byte-content to parameter
request.AddParameter(header, requestBytes.toArray(), ParameterType.RequestBody);
// Execute the request
IRestResponse response = client.Execute(request);
// Handle the response
if (response.IsSuccessful)
{
Console.WriteLine("File uploaded successfully!");
}
else
{
Console.WriteLine("File upload failed. Error: " + response.ErrorMessage);
}
}
}
just render the paramter by the order added would be sufficient. I believe you can set the file content type in the .AddFile() method but the overall content-type is still multipart/form-data
Body parameters are added to the request message in the same order as they are added to RestRequest
. But, files are added separately, as well as POST parameters when the content is a multipart form.
Duplicate of #2098
DO NOT USE ISSUES FOR QUESTIONS
Describe the bug when posting to an endpoint with File attachment, if there are other input parameters in the body, the File parameter is always render first regardless of the order the parameter is added.
To Reproduce call an api endpoint with file attachment and additional parameter like fileName and fileType.
` using var fileServiceClient = GetFileServiceClient(); var request = new RestRequest("file/v1/files", Method.Post);
`
Expected behavior Expected the http request to be:
POST https://somedomain.com/file/v1/files HTTP/1.1 Host: file-service.adsp-uat.alberta.ca Authorization: Bearer eyxxx Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml User-Agent: RestSharp/110.2.0.0 Accept-Encoding: gzip, deflate, br Content-Type: multipart/form-data; boundary="0a1f4db8-6981-4592-aff5-7b12b4e00197" Content-Length: 115113
--0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=type
tps-volume-titles --0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=filename
1680672668.csv --0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/csv Content-Disposition: form-data; name="file"; filename="1680672668.csv"
"xxx","2023-07-13 09:28:48",,ON00001,,"242006882001","S","*",,"2023-07-11","Subdivision Plan",,,"N",,"T","Fee Simple","242 006 882 +2",,,"2023-07-11"
--0a1f4db8-6981-4592-aff5-7b12b4e00197--
Actual rendered http request
POST https://somedomain.com/file/v1/files HTTP/1.1 Host: file-service.adsp-uat.alberta.ca Authorization: Bearer eyxxx Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml User-Agent: RestSharp/110.2.0.0 Accept-Encoding: gzip, deflate, br Content-Type: multipart/form-data; boundary="0a1f4db8-6981-4592-aff5-7b12b4e00197" Content-Length: 115113
--0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/csv Content-Disposition: form-data; name="file"; filename="1680672668.csv"
"xxx","2023-07-13 09:28:48",,ON00001,,"242006882001","S","*",,"2023-07-11","Subdivision Plan",,,"N",,"T","Fee Simple","242 006 882 +2",,,"2023-07-11"
--0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=type
tps-volume-titles --0a1f4db8-6981-4592-aff5-7b12b4e00197 Content-Type: text/plain; charset=utf-8 Content-Disposition: form-data; name=filename
1680672668.csv --0a1f4db8-6981-4592-aff5-7b12b4e00197--
Stack trace
Desktop (please complete the following information):
Additional context Add any other context about the problem here.