2017-01-23 1 views
0

Ich habe Probleme beim Hochladen eines Bildes in eine Web-API, die ich gerade aktiviere. Ich kann Daten von der Web-API abrufen, wenn ich GET-Anfragen verwende, aber ich habe Probleme mit POST-Anfragen. Ich muss ein BMP-Bild in die Web-API hochladen und dann eine JSON-Zeichenfolge zurücksenden.C# webrequest post image to web api

[HttpPost] 
public IHttpActionResult TestByte() 
{ 
    Log("TestByte function entered"); 
    //test to see if i get anything, not sure how to do this 
    byte[] data = Request.Content.ReadAsByteArrayAsync().Result; 
    byte[] test = Convert.FromBase64String(payload); 

    if(test == null || test.Length <= 0) 
    { 
     Log("No Payload"); 
     return NotFound(); 
    } 

    if (data == null || data.Length <= 0) 
    { 
     Log("No payload"); 
     return NotFound(); 
    } 

    Log("Payload received"); 
    return Ok(); 

} 

Das MVC-Seite, die das Bild sendet sieht wie folgt aus:

// Create a request using a URL that can receive a post. 
WebRequest request = WebRequest.Create(url); 
// Set the Method property of the request to POST. 
request.Method = "POST"; 

// Create POST data and convert it to a byte array. 
byte[] byteArray = GetImageData(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, content, barcodeUri)); 
string base64String = Convert.ToBase64String(byteArray); 
byte[] dataArray = Encoding.Default.GetBytes(base64String); 

// Set the ContentType property of the WebRequest. 
request.ContentType = "multipart/form-data"; 
// Set the ContentLength property of the WebRequest. 
request.ContentLength = dataArray.Length; 

// Get the request stream. 
Stream dataStream = request.GetRequestStream(); 
// Write the data to the request stream. 
dataStream.Write(dataArray, 0, dataArray.Length); 
// Close the Stream object. 
dataStream.Close(); 

// Get the response. 
WebResponse response = request.GetResponse(); 
// Get the stream containing content returned by the server. 
dataStream = response.GetResponseStream(); 
// Open the stream using a StreamReader for easy access. 
StreamReader reader = new StreamReader(dataStream); 
// Read the content. 
string responseFromServer = reader.ReadToEnd(); 
// Clean up the streams. 
reader.Close(); 
dataStream.Close(); 
response.Close(); 

Aus irgendeinem Grund habe ich immer eine 404 WebException bekommen

WebResponse response = request.GetResponse(); 

ich überprüft haben, dass die URL sein sollte Recht. Formatiere ich die URL für den Post oder mache ich einen anderen Fehler?

bearbeiten, hinzugefügt webconfig Routing:

public static void Register(HttpConfiguration config) 
{ 
    // Web API configuration and services 

    // Web API routes 
    config.MapHttpAttributeRoutes(); 

    config.Routes.MapHttpRoute(
     name: "DefaultApi", 
     routeTemplate: "api/{controller}/{action}/{id}", 
     defaults: new { id = RouteParameter.Optional } 
    ); 
} 
+0

Werfen Sie einen Blick [hier] (http://stackoverflow.com/questions/10320232/how-to-accept-a-file-post-asp-net-mvc-4-webapi) –

+0

Sie‘ Um den Inhalt als multipart/form-data zu setzen, aber der Stream nicht als multipart codiert ist, überprüfen Sie dies: http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data – Gusman

Antwort

1

Sie multipart/form-data nutzen, um die Datei zu übertragen. Hier ist ein Beispiel dafür, wie Sie den Inhalt der hochgeladenen Datei in Ihrem Web-API-Aktion lesen konnte:

[HttpPost] 
[Route("api/upload")] 
public async Task<IHttpActionResult> Upload() 
{ 
    if (!Request.Content.IsMimeMultipartContent()) 
    { 
     return this.StatusCode(HttpStatusCode.UnsupportedMediaType); 
    } 

    var filesProvider = await Request.Content.ReadAsMultipartAsync(); 
    var fileContents = filesProvider.Contents.FirstOrDefault(); 
    if (fileContents == null) 
    { 
     return this.BadRequest("Missing file"); 
    } 

    byte[] payload = await fileContents.ReadAsByteArrayAsync(); 
    // TODO: do something with the payload. 
    // note that this method is reading the uploaded file in memory 
    // which might not be optimal for large files. If you just want to 
    // save the file to disk or stream it to another system over HTTP 
    // you should work directly with the fileContents.ReadAsStreamAsync() stream 

    return this.Ok(new 
    { 
     Result = "file uploaded successfully", 
    }); 
} 

und jetzt einen Client schreiben, ist eine triviale Aufgabe mit der HttpClient:

class Program 
{ 
    private static readonly HttpClient client = new HttpClient(); 

    static void Main() 
    { 
     string responsePayload = Upload().GetAwaiter().GetResult(); 
     Console.WriteLine(responsePayload); 
    } 

    private static async Task<string> Upload() 
    { 
     var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost:8180/api/upload"); 
     var content = new MultipartFormDataContent(); 

     byte[] byteArray = ... get your image payload from somewhere 
     content.Add(new ByteArrayContent(byteArray), "file", "file.jpg"); 
     request.Content = content; 

     var response = await client.SendAsync(request); 
     response.EnsureSuccessStatusCode(); 

     return await response.Content.ReadAsStringAsync(); 
    } 
} 
+0

Für Irgendein Grund, warum ich eine 404 auf "response.EnsureSuccessStatusCode();" bekomme. Die URL, die ich anrufe, ist "http: // localhost: 49289/api/upload". Ich kann den localhost: 49289 in IIS express sehen. Ich habe im Grunde Ihren Code kopiert, keine Ahnung, warum ich nicht auf die Funktion in meiner Web-API zugreifen kann. – steuf

+0

Verwenden Sie das attributbasierte Routing in Ihrer Web-API? In meinem Beispiel habe ich aber davon ausgegangen, dass du es richtig konfiguriert hast. Wenn Sie globales Routing verwenden, dann passen Sie den Code an Ihr Szenario an, nicht nur blind kopieren und einfügen. –

+0

Ich habe attributbasiertes Routing in der Web-API aktiviert. Ich habe meine ursprüngliche Frage editiert, um meine WebApiConfig anzuzeigen. – steuf

0

löschen string payload Parameter von der TestByte-Methode. Es verursacht einen Fehler. Sie erhalten die Daten nach Request.Content.ReadAsByteArrayAsync Methode. Sie brauchen kein Nutzlastobjekt. Wenn Ihr Routing korrekt ist, muss es so funktionieren.

Bearbeiten: Können Sie routeTemplate so ändern?

routeTemplate: "api/{controller}/{id}" 
+0

Sie haben Recht mit dem Payload-Parameter, ich habe es hinzugefügt, um zu testen, ob es etwas ändern würde, ich habe es wieder entfernt. Ich benutze 'Request.Content.ReadAsByteArrayAsync', aber ich denke, es gibt ein Problem mit meinem Routing. Ich bin mir nicht sicher, was ich in meinem Routing suchen soll, um das Problem zu lösen. Es sollte funktionieren, aber beim Posten von Daten bekomme ich eine 404. – steuf

+0

habe ich für routeTemplate Wert bearbeitet. –