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;
}
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.
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