2016-07-08 34 views
0

Das Problem: Ist es möglich, Web Client zu verwenden, um eine HttpPostedFileBase (nur im Speicher verfügbar, nicht auf der Festplatte.) Zu einem anderen Endpunkt?Post multipart/Formulardatei aus Stream mit Web Client

Was ich versucht habe:

Ich habe die folgenden Controller, wir sind in einer Datei aus unserem Frontend veröffentlichen und es bindet an den Dateiparameter.

public class HomeController : Controller 
{ 
    [System.Web.Http.HttpPost] 
    public async Task<string> Index(HttpPostedFileBase file) 
    { 
     //file is not null here, everything works as it should. 

     //Here im preparing a multipart/form-data request to my api endpoint 
     var fileStreamContent = new StreamContent(file.InputStream); 
     using (var client = new HttpClient()) 
     using (var formData = new MultipartFormDataContent()) 
     { 
      formData.Add(fileStreamContent); 
      var response = await client.PostAsync("http://restapi.dev/api/files/add", formData); 
      var result = await response.Content.ReadAsStringAsync(); 
      return result; 
     } 
    } 
} 

Ich brauche diese Anfrage weitergeben zu einer anderen Anwendung, die nicht öffentlich zugänglich ist (so können wir nicht direkt vom Client post) Das Controller sieht wie folgt aus:

[RoutePrefix("api/files")] 
public class FilesController : ApiController 
{ 
    [HttpPost] 
    [Route("add")] 
    public async Task<HttpResponseMessage> Add(HttpPostedFileBase file) 
    { 
     //This is the problem, file is always null when I post from my backend. 
     var files = HttpContext.Current.Request.Files.Count > 0 ? HttpContext.Current.Request.Files[0] : null; 
     return Request.CreateResponse(HttpStatusCode.OK); 
    } 
} 

file ist immer null, so sind files. Was fehlt mir? Wenn ich Postman verwende und direkt auf den API-Endpunkt poste, funktioniert es. Also rate ich, dass ich etwas falsch mache in meinem HomeController?

+0

Also ist dies ein einfacher Proxy auf einen anderen Server? Was ist der erste Controller? MVC/WebAPI? Könnte es WebAPI sein? – spender

+0

Ja genau, der erste Controller ist ein MVC-Controller und der zweite ist ein WebAPI-Controller. Ich kann den Typ auf beiden ändern, wenn das Problem leichter zu lösen wäre. Idealerweise möchte ich die erste Anfrage direkt an meinen api-Controller weitergeben. – JOSEFtw

Antwort

1

Sie können dies mit neueren Technologie verbessern.

In WebAPI können Sie eine Controller-Methode wie folgt schreiben:

//[Route("api/Foo")] //maybe? 
[HttpPost] 
public async Task<HttpResponseMessage> MyResourceProxy(HttpRequestMessage request) 

jetzt können Sie diesen Wunsch übernehmen und schreiben ihre RequestUri Eigenschaft:

request.RequestUri = new Uri(blah); 

neu die Anfrage ein HttpClient und nach vorne oben :

HttpClient client = new HttpClient(); 
//make sure that this fails if it's hung for more than 30 seconds 
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); 
try 
{ 
    response = await client.SendAsync(request, 
             HttpCompletionOption.ResponseHeadersRead, 
             cts.Token); 
} 
catch (TaskCanceledException) 
{ 
    response = new HttpResponseMessage(HttpStatusCode.GatewayTimeout); 
} 

stellen Sie sicher, dass alles erhalten s angeordnet sind:

request.RegisterForDispose(new IDisposable[] {request, client, cts, response}); 

und ihn dann wieder response

return response; 

ich ein Timeout-Mechanismus, dass hinzugefügt nicht geeignet sein könnte für Sie braucht.

+0

Das sieht wirklich gut aus, es funktioniert, irgendwie. Ich empfange den folgenden Fehler (von meiner API) '' '{ " Nachricht ":" Es wurde keine HTTP-Ressource gefunden, die der Anfrage-URI 'http://restproxy.dev/api/files/add'. ", entspricht "MessageDetail": "Es wurde kein Typ gefunden, der mit dem Controller namens 'files' übereinstimmt." } '' ' Das ist seltsam, denn wenn ich versuche, auf diese URL direkt im Browser zuzugreifen, funktioniert es. Es fühlt sich an, als ob die Anfrage in meinem Controller in der falschen Anwendung aussieht, irgendwie ... wird weiter untersucht! – JOSEFtw

+0

@JOSEWtw Es sieht so aus, als ob Sie möglicherweise auch die Eigenschaft 'request.Headers.Host' ändern müssen. – spender

+1

ja! Das war's. Danke für deine Lösung, Mann, es ist wirklich sauber. Einen schönen Tag noch! – JOSEFtw