简体   繁体   中英

Send image with HttpClient to POST WebApi and consume the data

My HttpClient sends the image with PostAsync . I am not really sure what to do now since this is my first REST Api and I can't really adapt the things I sorted out in other posts yet. Hopefully you guys can help me out and can give me a direction.

public async Task SendImage(string fullFileName, string fileName)
    {            
        var client = new HttpClient();
        client.BaseAddress = new Uri("http://x.x.x.x");

        var content = new StringContent(fullFileName, Encoding.UTF8, "image/jpg");
        HttpResponseMessage response = await client.PostAsync($"/values/file/{fileName}", content);
    }

I have several questions about the POST function. First of all I can successfully access it with PostMan and the fileName is correct.

How do I read the image data and write it to a file?

[HttpPost("file/{fileName}")]
public void Upload(string fileName)
{        
    Debug.Write(fileName);
}

EDIT:

I setup my environment and I can now send a post via the internet to my published Web Api. On my app just nothing happens. For now I just tried to get something of a message to work on but I dont getting one.

[HttpPost("file/{fileName}")]
public HttpResponseMessage Upload(UploadedFile fileName)
{
    Debug.Write(fileName);
    if (!ModelState.IsValid)
    {

    }
    if (fileName == null)
    {

    }

    string destinationPath = Path.Combine(@"C:\", fileName.FileFullName);
    System.IO.File.WriteAllBytes(destinationPath, fileName.Data);
    HttpResponseMessage rm = new HttpResponseMessage();
    rm.StatusCode = HttpStatusCode.OK;
    return rm;
}

1.Your controller should look like this:

//For .net core 2.1
[HttpPost]
public IActionResult Index(List<IFormFile> files)
{
    //Do something with the files here. 
    return Ok();
}

//For previous versions

[HttpPost]
public IActionResult Index()
{
    var files = Request.Form.Files;
    //Do something with the files here. 
    return Ok();
}

2.To upload a file you can also use Multipart content:

        public async Task UploadImageAsync(Stream image, string fileName)
        {
            HttpContent fileStreamContent = new StreamContent(image);
            fileStreamContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { Name = "file", FileName = fileName };
            fileStreamContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
            using (var client = new HttpClient())
            using (var formData = new MultipartFormDataContent())
            {
                formData.Add(fileStreamContent);
                var response = await client.PostAsync(url, formData);
                return response.IsSuccessStatusCode;
            }
         }

3.If you are uploading large files you should consider streaming the files instead, you can read about it here

You're going fine until you're trying to retrieve the image data, I'm afraid.

According to your question:

How do I read the image data and write it to a file?

All you want to do is getting the file's data and its file name and sending it to your service.

I would personally create an UploadedFile class on both sides (client and service side), having the file's name and its data, so:

public class UploadedFile
{
    public string FileFullName { get; set; }
    public byte[] Data { get; set; }

    public UploadedFile(string filePath)
    {
        FileFullName = Path.GetFileName(Normalize(filePath));
        Data = File.ReadAllBytes(filePath);
    }

    private string Normalize(string input)
    {
        return new string(input
                .Normalize(System.Text.NormalizationForm.FormD)
                .Replace(" ", string.Empty)
                .ToCharArray()
                .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                .ToArray());
    }
}

Then you will need, for example, the NewtonSoft's JsonConvert in order to serialize the object and send it through.

So now you would be able to send your data async:

public async Task SendDataAsync(string fullFilePath)
{
    if (!File.Exists(fullFilePath))
        throw new FileNotFoundException();
    var data = JsonConvert.SerializeObject(new UploadedFile(fullFilePath));
    using (var client = new WebClient())
    {
        client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
        await client.UploadStringTaskAsync(new Uri("http://localhost:64204/api/upload/"), "POST", data);
    }
}

Now, make sure you correctly handle the request on the server side. If for whatever reason the parameters doesn't match it won't enter into the method (remember having the same model/class - UploadedFile on the service as well).

On the service, just change the arguments of your method and perform something "like this":

[HttpPost]
public HttpResponseMessage Upload(UploadedFile file)
{
    if (!ModelState.IsValid)
        ...

    if (file == null)
        ...
    string destinationPath = Path.Combine(_whateverPath, file.FileFullName);
    File.WriteAllBytes(destinationPath, file.Data);
}

Hope it helped you having an idea about what to do and what you're actually doing wrong. I've exposed something similar based in my experience.

EDIT : I've actually uploaded an example with both sides working: a simple .NET Core console app which retrieves a file and sends it through POST and a basic WebAPI2 service with a simple controller to retrieve the data. Both ready to go and tested working! Download it here .

Enjoy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM