Reputation: 722
I'm trying to use a component (slim image cropper) to crop images then send both the original image and the cropped version to my server through a Web API. My problem here is that I get the data as a blob array (the first element is the original and the second is cropped) and I have absolutely no idea how to send that data, or how to transform it to be able to send it to my API.
I'm using a javascript function instead of a direct service call to pass more parameters, as supported by the component and documented here.
Here's the function :
var uploadImage = function (formdata, progress, success, failure) {
var originalArray;
var croppedArray;
var apiCall = function (original, cropped) {
var params = {
name: formdata[0].name,
original,
cropped,
id: $('hidId').val()
}
$.getJSON('/api/Test/UploadImage', params, function (response) {
if (response) {
if (response.Success == true) {
success('Upload réussi')
} else {
failure('Upload échoué')
}
} else {
failure('Pas de réponse de l\'API')
}
});
};
var originalReader = new FileReader();
originalReader.onloadend = function () {
originalArray = originalReader.result;
if (originalArray != null && croppedArray != null)
apiCall(originalArray, croppedArray);
};
originalReader.readAsArrayBuffer(formdata[0]);
var croppedReader = new FileReader();
croppedReader.onloadend = function () {
croppedArray = croppedReader.result;
if (originalArray != null && croppedArray != null)
apiCall(originalArray, croppedArray);
};
croppedReader.readAsArrayBuffer(formdata[1]);
}
I know it must look sketchy, but I have no experience at all with that case. When I get to the $.getJSON(...) line, I get a 404 error in the console, showing that only the "name" parameter is passed.
Just in case it's relevant, here's my API method signature:
public IHttpActionResult UploadImages(string name, byte[] original, byte[] cropped, Guide id)
{
...
}
How can I solve this and send the images? What should be the parameter type on the API side?
Upvotes: 2
Views: 5566
Reputation: 649
If you are using regular MVC, then you should use a request using AJAX with FormData, in other words, you create a FormData object then add the Blob, and send, in the server a method using IFormFile must save the file.
If you are using Blazor, what I did was create a reference to the InputFile, then pass this reference to a JavaScript function using IJSRuntime, on JS then I can read what the input[file] and I will produce a Base64 string, that I send back to be used and saved as a string on my db... REASON: Blazor is useless compressing images, it produces a Base64 string but for some reason, it damages the image and shows only a piece of it.
Upvotes: 0
Reputation: 31024
You can use a form
with the enctype="multipart/form-data"
attribute (you can submit that form via ajax)
And received it as a HttpPostedFileBase type on the server-side.
For Example taken from here:
<form action="" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" />
</form>
[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
if (file.ContentLength > 0) {
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
file.SaveAs(path);
}
return RedirectToAction("Index");
}
EDIT
For multiple files you can use the input's attribute multiple="multiple"
and in the server-side accept a collection of HttpPostedFileBase
like IEnumerable<HttpPostedFileBase>
.
<input type="file" multiple="multiple" name="files" id="files" />
Upvotes: 1