Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using FileReader.readAsDataUrl to upload image to Web Api service

I am trying to use the FileReader to obtain the base-64 representation of an image and submit that to a .net WebApi service for image uploading.

My problem is that the contents of fileReader.result are not valid as a base-64 encoded image, at least according to .net.

I am just using a very simple method, and testing with fiddler to post to the service. If I post the complete result string from filereader.result, I get an error "Invalid length for a Base-64 char array or string" when I try and read the string using FromBase64String.

public void Post([FromBody]string imgString)
    {
        var myString = imgString.Split(new char[]{','});
        byte[] bytes = Convert.FromBase64String(myString[1]);
        using (MemoryStream ms = new MemoryStream(bytes))
        {
            Image image = Image.FromStream(ms);
            image.Save("myBlargyImage.jpg");
        }
    }

Is cut+paste into fiddler doing something to the string that I need to account for here, or is there something else I am not doing correctly? This seems like it should be straightforward: Encode the image as a string, send the string, decode the string, save the image.

For example, using filereader to display a preview of the image on the client, I get the following in filereader.result:

src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEAyADIAAD/...oBUA00AqYL/AMCg3//Z"

I have tried both sending the entire string ("data...Z"), and just the Base64 string. Currently, I am splitting the string server side to get the Base64 string. Doing this, I always get the invalid length error.

Alternatively, I have tried sending just the base64 string. Not knowing if the leading / was actually part of the string or not, I deleted it in the post body. Doing THIS, I can actually read the value into a byte array, but then I get an error using Image.FromStream that the array is not a valid image.

So, either I get an error that the entire string as provided by filereader is an invalid length, or, I hack it up and get an error that even if it is a valid length, it is not a valid image (when reading the bytearray). That is what makes me wonder if there is some issue of translation or formatting between the filereader.read, dev tools in chrome, then cutting and pasting into fiddler.

UPDATE: I tried a more realistic implementation by just taking the filereader.result and putting it in a $.post() call, and it works as expected.

It appears I was right, that I, or notepad++, or fiddler, are doing something to the data when I touch it to cut and paste filereader.result into a service call.

If someone knows exactly what that might be, or how one can verify they are sending a valid base-64 encoding of an image to a service, it might help others who are attempting the same thing in the future.

Again, if in the browser filereader.result yielded 'data:image/jpeg;base64,somestring', I was simply copying that string from the developer tools panel, creating a fiddler call and in the request body including the copied string: "=data:image/jpeg;base64,somestring". Somehow, the base-64 'somestring' was getting munched in the cut+paste.

function readURL(input) {

        if (input.files && input.files[0]) {
            reader = new FileReader();

            reader.onload = function (e) {
                $('#imgPreview').attr('src', e.target.result);
                $.post('/api/testy/t/4',
                    {'':e.target.result}
                );
            };

            reader.readAsDataURL(input.files[0]);
            reader.onloadend = function (e) {
                console.log(e.target.result);
            };
        }
    }

    $("#imgUpload").change(function () {
        readURL(this);
    });
like image 872
monkeydeus Avatar asked Jan 07 '14 01:01

monkeydeus


People also ask

How do I use FileReader API?

FileReader can only access the contents of files that the user has explicitly selected, either using an HTML <input type="file"> element or by drag and drop. It cannot be used to read a file by pathname from the user's file system. To read files on the client's file system by pathname, use the File System Access API.

How do you use readAsDataURL?

The readAsDataURL method is used to read the contents of the specified Blob or File . When the read operation is finished, the readyState becomes DONE , and the loadend is triggered. At that time, the result attribute contains the data as a data: URL representing the file's data as a base64 encoded string.

Can FileReader read URL?

Solution 1. No, FileReader is not designed to read remote resources via URL.

What does FileReader return?

The FileReader result property returns the file's contents. This property is only valid after the read operation is complete, and the format of the data depends on which of the methods was used to initiate the read operation.


2 Answers

Don't forget to remove the 'noise' from a dataUrl,

For example in

data:image/png;base64,B64_DATA_HERE

you have to remove the data:image/png;base64, part before, so you process only the base 64 portion.

With js, it would be

var b64 = dataUrl.split("base64,")[1];

Hope this helps. Cheers

like image 159
Edgar Villegas Alvarado Avatar answered Sep 30 '22 21:09

Edgar Villegas Alvarado


A data uri is not a base64 encode string, it may contain a base64 encoded string at the end of it. In this case it does, so you need to only send the base64 encoded string part.

var imagestr = datauri.split(',')[1];
sendToWebService(imagestr);
like image 20
Musa Avatar answered Sep 30 '22 20:09

Musa