2017-01-23 5 views
0

У меня возникли проблемы с загрузкой изображения в веб-API, который я запускаю. Я могу извлекать данные из веб-API при использовании запросов GET, но у меня возникают проблемы с запросами POST. Мне нужно загрузить изображение BMP в веб-API, а затем отправить обратно строку json.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(); 

} 

сторона MVC, которая отправляет изображение выглядит следующим образом:

// 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(); 

По некоторым причинам я всегда получаю 404 WebException на

WebResponse response = request.GetResponse(); 

Я проверил, что URL должен быть правильно. Это как я отформатирую URL для сообщения, или я делаю какую-то другую ошибку?

Edit, добавлена ​​WebConfig маршрутизации:

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

Посмотрите [здесь] (http://stackoverflow.com/questions/10320232/how-to-accept-a-file-post-asp-net-mvc-4-webapi) –

+0

Вы» повторно устанавливая содержимое как multipart/form-data, но поток не кодируется как multipart, проверьте это: http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data – Gusman

ответ

1

Вы можете использовать multipart/form-data для передачи файла. Вот пример того, как вы могли бы прочитать содержимое загруженного файла в веб-действия API:

[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", 
    }); 
} 

и теперь пишу клиент является нетривиальной задачей, используя 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

Для по какой-то причине я получаю 404 на 'response.EnsureSuccessStatusCode();'. URL, который я вызываю, это «http: // localhost: 49289/api/upload», я вижу локальный хост: 49289, работающий в IIS express. Я в основном скопировал ваш код, не знаю, почему я не могу получить доступ к функции в моем веб-API. – steuf

+0

Вы используете маршрутизацию на основе атрибутов в своем веб-API? В моем примере я сделал это, но это предполагает, что вы правильно настроили его. Если вы используете глобальную маршрутизацию, то адаптируйте код к вашему сценарию, не просто слепо копировать-вставить. –

+0

У меня есть маршрутизация, основанная на атрибутах, включенная в веб-API, я редактировал свой оригинальный вопрос, чтобы показать мой WebApiConfig. – steuf

0

Удалить string payload параметр из метода TestByte. Это вызывает ошибку. Вы получаете данные по методу Request.Content.ReadAsByteArrayAsync. Вам не нужен объект полезной нагрузки. Если ваша маршрутизация верна, она должна работать следующим образом.

Редактировать: Можете ли вы изменить routeTemplate, как это?

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

Вы правы в параметре полезной нагрузки, я добавил его, чтобы проверить, изменит ли он что-то, я удалил его снова. Я использую 'Request.Content.ReadAsByteArrayAsync', но я думаю, что есть проблема с моей маршрутизацией. Я не уверен, что искать в моей маршрутизации, чтобы решить проблему. Он должен работать, но при отправке данных я получаю 404. – steuf

+0

Я отредактировал для значения routeTemplate. –