Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multipart Content with refit

Tags:

c#

.net

refit

I am using multipart with Refit. I try to upload profile picture for my service the code generated from postman is looking like this

var client = new RestClient("http://api.example.com/api/users/1");
var request = new RestRequest(Method.POST);
request.AddHeader("Postman-Token", "xxx");
request.AddHeader("Cache-Control", "no-cache");
request.AddHeader("content-type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
request.AddParameter("multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW", "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"_method\"\r\n\r\nput\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"profile_picture\"; filename=\"ic_default_avatar.png\"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

and then I construct Refit method like this

[Multipart]
[Post("/users/{id}")]
IObservable<BaseResponse<User>> UpdateProfilePicture(int id,[AliasAs("profile_picture")] byte[] profilePicture,[AliasAs("_method")]string method="put");

if I use byte[] or ByteArrayPart it will throw exception

{System.Net.Http.HttpRequestException: An error occurred while sending the request ---> System.Net.WebException: Error getting response stream (chunked Read2): ReceiveFailure ---> System.Exception: at System.Net.WebConnection.HandleError (System.Net.WebExceptionStatus st, System.Exception e, System.String where) [0x00031] in :0 at System.Net.WebConnection.Read (System.Net.HttpWebRequest request, System.Byte[] buffer, System.Int32 offset, System.Int32 size) [0x000d2] in :0 at System.Net.WebConnectionStream.ReadAll () [0x0010e] in :0 at System.Net.HttpWebResponse.ReadAll () [0x00011] in :0 at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x001d6] in :0 at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x0013e] in :0 at System.Net.WebConnection.ReadDone (System.IAsyncResult result) [0x0024d] in :0 at System.Net.Sockets.SocketAsyncResult+<>c.b__27_0 (System.Object state) [0x00000] in :0 at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00015] in :0 at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in :0 at ObjCRuntime.Runtime.ThreadPoolDispatcher (System.Func`1[TResult] callback) [0x00006] in <0b60c1467e7449608ac42f9c7bbfdd05>:0 at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00009] in :0 at System.Net.WebConnection.HandleError (System.Net.WebExceptionStatus st, System.Exception e, System.String where) [0x00031] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.12.0.4/src/Xamarin.iOS/mcs/class/System/System.Net/WebConnection.cs:439

. and if I use Stream or StreamPart it will also throw exception said stream is closed.

like image 427
albilaga Avatar asked Aug 08 '18 18:08

albilaga


2 Answers

You can use IEnumerable<StreamPart> to upload a files:

  [Multipart]
  [Post("/users/{id}")]
  Task UpdateProfilePicture(int id, [AliasAs("profile_picture")] IEnumerable<StreamPart> streams);
like image 85
Hossein Avatar answered Sep 18 '22 16:09

Hossein


It's an old question, but maybe it could help others.

I wasn't able to use StreamPart either since the file size received on the server side was always 0 so I used ByteArrayPart instead like specified here github.com/reactiveui/refit#multipart-uploads.

Interface:

[Multipart]
[Post("/api/<some-path>")]
Task<HttpResponseMessage> Upload([AliasAs("file")] ByteArrayPart bytes);

Usage:

var stream;
using (MemoryStream ms = new MemoryStream())
{
    stream.CopyTo(ms);
    client.Upload(new ByteArrayPart(ms.ToArray(), fileName));
}

Note that this technique will load the entire stream in memory! It worked for me, because I had small files, but you should find a better way if you are dealing with large files or memory usage is an issue.

like image 27
Maxime Gélinas Avatar answered Sep 20 '22 16:09

Maxime Gélinas