Mirodinho
Mirodinho

Reputation: 1321

Microsoft Cognitive Services: Uploading image

I am trying to upload an image to the Microsoft Computer Vision API from a mobile device, but I am constantly receiving a 400 Bad Request for Invalid File Format "Input data is not a valid image". The documentation states that I can send the data as application/octet-stream in the following form:

[Binary image data]

I have the data of the image in terms of base64 encoding ("/9j/4AAQSkZJ.........."), and I also have the image as a FILE_URI, but I can't seem to figure out the format in which to send the data. Here is a sample code:

$(function() {
    $.ajax({
        url: "https://api.projectoxford.ai/vision/v1.0/describe",
        beforeSend: function (xhrObj) {
            // Request headers
            xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
            xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", computerVisionKey);
        },
        type: "POST",
        // Request body
        data: base64image,
        processData: false        
    })
    .done(function(data) {
      alert("success");
    })
    .fail(function(error) {
      alert("fail");
    });
});

I've tried the following:

and more.

I did tested these on the Computer Vision API console. Is it because base64 encoded binary isn't an acceptable format? Or am I sending it in the incorrect format completely?

Note: The operation works when sending a URL as application/json.

Upvotes: 2

Views: 4573

Answers (2)

Pete
Pete

Reputation: 21

Just wanted to add this in case it helps anyone else. The answer referenced by cthrash above works fine, but it lead me to a simpler way that doesn't convert the image to base64 and then back to binary.

Just read the image as an ArrayBuffer and use that to construct a new Blob for the body of the post. Also, don't forget to set processData to false. The full solution looks like this:

//onChange event handler for file input
function fileInputOnChange(evt) {
    var imageFile = evt.target.files[0];     
    var reader = new FileReader();
    var fileType;

    //wire up the listener for the async 'loadend' event
    reader.addEventListener('loadend', function () {

        //get the result of the async readAsArrayBuffer call
        var fileContentArrayBuffer = reader.result;

            //now that we've read the file, make the ajax call
            $.ajax({
                url: "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect",
                beforeSend: function (xhrObj) {
                    // Request headers
                    xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
                    xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", "<your subscription key goes here>");
                },
                type: "POST",

                //don't forget this!
                processData: false,

                //NOTE: the fileContentArrayBuffer is the single element 
                //IN AN ARRAY passed to the constructor!
                data: new Blob([fileContentArrayBuffer], { type: fileType })
            })
            .done(function (data) {
                console.log(data)
            })
            .fail(function (err) {
                console.log(err)
            });

    });
    if (imageFile) {
        //save the mime type of the file
        fileType = imageFile.type;

        //read the file asynchronously
        reader.readAsArrayBuffer(imageFile);
    }    
}

Upvotes: 1

cthrash
cthrash

Reputation: 2973

Please take a look at Emotion API Project Oxford base64 image, or go directly to the code snippet here: How to post an image in base64 encoding via .ajax? .

Since this is a recurring topic, I've made a feature request to make the APIs handle data URIs directly, on UserVoice.

Upvotes: 3

Related Questions