2

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?

1
  • i usually do it with a form that has the enctype="multipart/form-data" attribute (you can submit it via ajax) and in the serverside accept it as a HttpPostedFileBase type msdn.microsoft.com/en-us/library/… Commented Aug 29, 2017 at 21:58

2 Answers 2

1

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" />
Sign up to request clarification or add additional context in comments.

8 Comments

I already implemented the component like this, the problem is that sending the data with a regular form posting only allows me to get the cropped image and not the original. After a long mail exchange with the component's author (very helpful and reactive btw), it resulted that I can only achieve what I want through ajax...
Still, upvoted as it's a valid solution when you only need the cropped version. Note, though, that the file is then passed as a json object with the base64 image data instead of a HttpPostedFileBase.
you can submit forms via ajax, and you can have an input of type file with the multiple attribute, that will let the user choose more than one file. i've done this before and it works quite well
looking at their docs, this is exactly what they ask you to do on the client side: slimimagecropper.com/#form-post
I know, but then again the component is built in a way that you only get the cropped image when you use a form post, and the data is passed as json (the component transforms the file input into a hidden input containing said json). This is perfectly fine in most cases when you only need the cropped version, but not when you try to get both as I'm trying to do.
|
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.