简体   繁体   中英

How to upload jpeg file using jQuery ajax?

The solutions I've found on SO haven't helped. I'm always getting the error '415 (Unsupported Media Type)'. But when I use Postman to upload a file to our server, it works. What am I doing wrong with this code?

var form = new FormData();
form.append("", "<path-to-jpeg-file>");

var settings = {
  "async": true,
  "crossDomain": true,
  "url": "<api url>",
  "method": "POST",
  "headers": {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": "Bearer dP1K7UfZSko4vT3RyVH02...",
    "cache-control": "no-cache"
  },
  "processData": false,
  "contentType": false,
  "mimeType": "multipart/form-data",
  "data": form
}

$.ajax(settings).done(function (response) {
  console.log(response);
});

I've also read on SO that I have redundant content type declarations, so I tried it by removing "Content-Type": "application/x-www-form-urlencoded", and also tried removing "mimeType": "multipart/form-data" and still get the same error. And again, if I use Postman to upload the file, it works (so it's not a server problem). Postman also has a way to generate the code for ajax. I copied and pasted the generated code into my app and still get the same error. What is the proper way to upload a file (in this case, jpg) using ajax?

You have two problems.


You aren't loading the file

 var form = new FormData(); form.append("", "<path-to-jpeg-file>"); 

Here you:

  1. Haven't given the data a name, so it won't appear in the request
  2. You are trying to send a string path instead of the actual data

Replace that with:

var form = new FormData( document.getElementById("yourForm") );

Make sure the form includes an <input type="file" name="something"> .


You are breaking the information in the request needed to decode it

You are setting the Content-Type header using three different techniques:


This attempt is completely wrong. You aren't sending URL encoded data.

Remove this.

  "headers": { "Content-Type": "application/x-www-form-urlencoded", 

This is pretty wrong. You are sending multiparty data, but you are missing the mandatory boundary parameter.

Remove this too.

  "mimeType": "multipart/form-data", 

This is correct. You are telling jQuery not to set a contentType at all which allows XMLHttpRequest to extrapolate it from the FormData object.

Keep only this one.

  "contentType": false, 

All this assumes that the server is expecting a POST request with a multipart body.

You haven't shown us the details of the request you are successfully making with Postman or the documentation for the API.

After trying several different variations of configs, different ways to read a file, and with a little help from the people on this page, I've finally got everything working. I hope this saves other people who aren't very familiar with client-side web dev some time and trouble. I use Q promises here, but you can use any promise, and I'm sure there are a few defects (like error handling), but at least I've got file upload working!:

const readFile = (fileURI) => {
    return Q.Promise((resolve, reject) => {
        try {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', fileURI);
            xhr.responseType = 'blob';
            xhr.onload = () => {
                const blob = xhr.response;
                const reader = new FileReader();
                reader.onload = () => {
                    const data = reader.result.split(',').pop();
                    resolve(data);
                };

                reader.onerror = () => {
                    reject('error reading file');
                };

                reader.readAsDataURL(blob);
            };

            xhr.onerror = () => {
                reject('unable to read image data');
            };

            xhr.send();
        } catch (e) {
            reject(e.message);
        }
    });
};

const uploadImage = (fileURI) => {
    readFile(fileURI)
    .then((data) => {
        const formData = new FormData();
        formData.append('base64', data);

        $.ajax({
            type: 'POST',
            url: '<endpoint url>',
            contentType: false,
            processData: false,
            headers: {
                'cache-control': 'no-cache'
            },
            data: formData,
            beforeSend: (xhr) => {
                xhr.setRequestHeader('Authorization', this.auth);
            },
            success: (res) => {
                logger.info(`request success: ${JSON.stringify(res)}`);
            },
            error: (error) => {
                logger.info(`request unsuccessful: ${error.statusText}`);
            }
        });
    })
    .catch((e) => {
        logger.info(`An error occurred: ${e}`);
    })
};

It took me a day and a half to figure this out! I'll fix the promises a bit now that I've got things working.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM