原生js上传图片遇到的坑

Posted 人在路途

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生js上传图片遇到的坑相关的知识,希望对你有一定的参考价值。

后台给我写了一个上传图片的接口,自己用form表单测试成功

 

 

 接口可以正常跳转

 

 

 测试的代码:

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
 </head>
 <body>
  <form method="POST" action="http://192.168.79.191:8889/api/upload/uploadFile" enctype="multipart/form-data">
    <table>
        <tr>
            <td><label path="file">Select a file to upload</label></td>
            <td><input type="file" name="file" id="upload_file"/></td>
        </tr>
        <tr>
            <td>fileGroup: <input name = "fileGroup" type = "text"><br></td>
        </tr>
        <tr>
            <td>flag:<input name = "flag" type = "text"><br></td>
        </tr>
        <tr>
            <td><input type="submit" value="Submit"/></td>
        </tr>
    </table>
</form>
 </body>
</html>
View Code

 

因为这样用form表单提交的时候会自动跳转,所以就想到用js模拟form表单提交

 

代码一写完,问题来了,用axios请求不成功,

let file = e.target.files[0]
var formData = new FormData()
formData.append(\'file\', file)
this.$ajax.post(Api.uploadFile, formData).then(function(response) {
    alert(123)
    //this.$refs.loading.show()
    if (response.data.status === -1) {
        //this.promptText = response.data.msg
        //this.$refs.prompt.show()
    } else {
        //this.front_pic = this.publicUrl + response.data.data.url // 提交图片获取URL,返回
    }
}, function() {
    this.promptText = \'请求失败\'
    this.$refs.prompt.show()
})

 

 

然后我想axios不成功,那我换成了原生的ajax请求应该行了吧结果还是不成功,代码如下

/*原生请求方式 */
let xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
xhr.open("post", "http://localhost:8082/api/files/api/upload/uploadFile", true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
xhr.setRequestHeader(\'content-type\', \'multipart/form-data\')//不要自作多情加上这一句
//xhr.setRequestHeader(\'Accept\', \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\')
xhr.send(formData); //开始上传,发送form数据
xhr.onreadystatechange = function () {
    var data = xhr.responseText;
    console.log(data);
}

控制台 network  就是请求不成功,500报错

 

 错误信息如下

 

 

整了大半天,最后发现是不用设置content-type   一去掉就正常了  真的是自作多情 自己设置了content-type导致请求不成功

总结问题:

第一:axios不成功

原因:

1、自作多情设置了content-type(拦截器李阿敏)

//http request 拦截器
axios.interceptors.request.use(
  config => {
    config.headers = {
      //\'Content-Type\':\'application/x-www-form-urlencoded\'
      \'Content-Type\': \'multipart/form-data\'
    }
    return config;
  },
  error => {
    return Promise.reject(err);
  }
);

 

2、axios可能将请求污染

解决办法:

请求之前先new 一个全新的axios  如下

    uploadImage(e){
      let instance = axios.create();//请求之前先new一个全新的axios
      let file = e.target.files[0]
      const formDate = new FormData()
      formDate.append(\'file\', file)

      instance.post(\'/files/api/upload/uploadFile\',formDate).then((res)=>{
            console.log(res);
            if(res.status && res.status == 500){
                this.error=\'用户名或密码错误!\'
            }else if(res.access_token){
                let millisecond = new Date(new Date().getTime() + res.expires_in * 1000);   //access_token过期时间
                cookies.set(\'access_token\',res.access_token,{expires: millisecond});    //设置cookie
                this.$router.replace("/");  //登录到首页
            }
        })
    }

上面代码:正常,可以请求成功,问题得到解决

 

第二:原生的ajax不成功

原因  设置了content-type

解决办法:将content-type去掉

 

 

 

上传图片组件代码

<template>
    <div class="param-pannel">

        <common-prm/>
        <border-prm myStyle="style" />
        <collapse-item title="图片">

            <div class="param-gap">
                <label class="left" for="">路径&nbsp;:</label>
                <div class="right">

                    <input type="file" 
                    name="file"
                    ref="input"
                    enctype="multipart/form-data"
                    accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" 
                    multiple="multiple" 
                    @change="getFile" 
                    class="data-value" />

                </div>
            </div>

        </collapse-item>
    </div>
</template>
<script>
import axios from \'axios\'
import mixins from \'../paramMixins.js\'
import Api from \'@frameworks/conf/api\'
export default {
    name: \'ImgParam\',
    mixins: [mixins],
    data() {
        return {
            textName: \'文本\'
        }
    },
    methods: {
        getFile(e) {
            //验证
            if (e.target.files[0].size >= 1048576) {
                alert("上传图片大小不得超过1M");
                return false;
            }
            // 预览图片
            var reader = new FileReader();
            let _this = this
            reader.onload = (function(file) {
                return function(e) {
                    var datainfo = this.result;
                    _this.params.images = datainfo
                    _this.updateData()
                    
                };
            })(e.target.files[0]);
            reader.readAsDataURL(e.target.files[0]);
            //上传
            this.upload(e.target.files[0])
        },
        //调用上传图片的接口上传
        upload(file){
            var formData = new FormData()
            formData.append(\'file\', file)
            /*axios请求方式 */
            this.$ajax.upload(Api.uploadFile, formData).then(function(response) {
                if (response.data.status === -1) {
                    alert()
                } else {

                }
            }, function() {
                this.promptText = \'请求失败\'
                this.$refs.prompt.show()
            })
            //axios封装的post请求(不成功)
            /*this.$ajax.post(Api.uploadFile, formData).then(function(response) {
                alert(123)
                
            }, function() {
                this.promptText = \'请求失败\'
                this.$refs.prompt.show()
            })*/
            /*原生请求方式(成功) */
            // let xhr = new XMLHttpRequest();  // XMLHttpRequest 对象
            // xhr.open("post", "http://localhost:8082/api/files/api/upload/uploadFile", true); //post方式,url为服务器请求地址,true 该参数规定请求是否异步处理。
            // //xhr.setRequestHeader(\'content-type\', \'multipart/form-data\')
            // //xhr.setRequestHeader(\'Accept\', \'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\')
            // xhr.send(formData); //开始上传,发送form数据
            // xhr.onreadystatechange = function () {
            //     var data = xhr.responseText;
            //     console.log(data);
            // }
        }
    }
}
</script>

<style scoped lang="scss">
.param-pannel input,
.param-pannel select {
    border: 1px solid #ddd;
    width: 100%
}

.param-pannel>div {
    padding: 5px 0;
}
</style>


<style scoped lang="scss">
@import \'../../../assets/css/params_common.scss\';
</style>
View Code

 

封装的axios

import axios from \'axios\';
import {axios_defaults_timeout} from \'@frameworks/conf/config\'
import qs from \'qs\'

axios.defaults.timeout = axios_defaults_timeout;
axios.defaults.baseURL = JSON.parse(process.env.VUE_APP_MICRO_SERVICE)?process.env.VUE_APP_URL:process.env.VUE_APP_SINGLEURL; //填写域名

//http request 拦截器
axios.interceptors.request.use(
  config => {
    config.headers = {
      //\'Content-Type\':\'application/x-www-form-urlencoded\'
      \'Content-Type\': \'multipart/form-data\'
    }
    return config;
  },
  error => {
    return Promise.reject(err);
  }
);

//响应拦截器即异常处理
axios.interceptors.response.use(response => {
    return response
}, err => {
    if (err && err.response) {
      switch (err.response.status) {
        case 400:
          return Promise.resolve({status:err.response.status,message:\'错误请求\'});
          break;
        case 401:
          return Promise.resolve({status:err.response.status,message:\'未授权,请重新登录\'});
          break;
        case 403:
          return Promise.resolve({status:err.response.status,message:\'拒绝访问\'});
          break;
        case 404:
          return Promise.resolve({status:err.response.status,message:\'请求错误,未找到该资源\'});
          break;
        case 405:
          return Promise.resolve({status:err.response.status,message:\'请求方法未允许\'});
          break;
        case 408:
          return Promise.resolve({status:err.response.status,message:\'请求超时\'});
          break;
        case 500:
          return Promise.resolve({status:err.response.status,message:\'服务器端出错\'});
          break;
        case 501:
          return Promise.resolve({status:err.response.status,message:\'网络未实现\'});
          break;
        case 502:
          return Promise.resolve({status:err.response.status,message:\'网络错误\'});
          break;
        case 503:
          return Promise.resolve({status:err.response.status,message:\'服务不可用\'});
          break;
        case 504:
          return Promise.resolve({status:err.response.status,message:\'网络超时\'});
          break;
        case 505:
          return Promise.resolve({status:err.response.status,message:\'http版本不支持该请求\'});
          break;
        default:
          return Promise.resolve({status:err.response.status,message:\'未知错误\'});
          break;
      }
    } else {
      return Promise.resolve({status:err.response.status,message:\'连接到服务器失败\'});
    }
    return Promise.resolve(err.response)
})


/**
 * 封装get方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function fetch(url,params={}){
  return new Promise((resolve,reject) => {
    axios.get(url,{
      params:params
    })
    .then(response => {
      if(response.data) resolve(response.data);
    })
    .catch(err => {
      reject(err)
    })
  })
}


/**
 * 封装上传图片upload的方法
 * @param url
 * @param data
 * @returns {Promise}
 */
 export function upload(url,data = {}){
   let instance = axios.create();
   return new Promise((resolve,reject) => {
     instance.post(url,data)
      .then(response => {
        if(response.data) resolve(response.data);
      },err => {
        reject(err)
      })
   })
 }

/**
 * 封装post请求
 * @param url
 * @param data
 * @returns {Promise}
 */
 export function post(url,data = {}){
   return new Promise((resolve,reject) => {
     axios.post(url,qs.stringify(data))
      .then(response => {
        if(response.data) resolve(response.data);
      },err => {
        reject(err)
      })
   })
 }

 /**
 * 封装patch请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function patch(url,data = {}){
  return new Promise((resolve,reject) => {
    axios.patch(url,data)
         .then(response => {
           if(response.data) resolve(response.data);
         },err => {
           reject(err)
         })
  })
}

 /**
 * 封装put请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function put(url,data = {}){
  return new Promise((resolve,reject) => {
    axios.put(url,data)
         .then(response => {
           if(response.data) resolve(response.data);
         },err => {
           reject(err)
         })
  })
}

 /**
 * 封装delete请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function del(url,data = {}){
  return new Promise((resolve,reject) => {
    axios.delete(url,data)
         .then(response => {
           if(response.data) resolve(response.data);
         },err => {
           reject(err)
         })
  })
}


 /**
 * 封装异步Ajax请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export async function syncAjax (url = \'\',method = \'get\',data = {},callbackr = ()=>{},callbackw = ()=>{}) {
  try {
    let response = await axios({ method, url, data })
    callbackr && callbackr(response)
    return Promise.resolve(response)
  } catch (err) {
    callbackw && callbackw(err)
    return Promise.reject(err)
  }
}

const ajax = {
  fetch,post,patch,put,del,syncAjax,upload
}

export default ajax
View Code

 

封装的jq ajax

import $ from \'jquery\';

export default function jqueryAjax(url,method,async,data,callbackr,callbackw) {
  $.ajax({
    url: url, //url路径
    type: method, //GET
    async: async, //或false,是否异步
    data: data,
    timeout: 5000, //超时时间
    dataType: \'json\', //返回的数据格式
    beforeSend: function(xhr) {},
    success: function(data, textStatus, jqXHR) {
      callbackr && callbackr(data);
    },
    error: function(xhr, textStatus) {
      callbackw && callbackw(xhr);
    },
    complete: function() {}
  })
}
View Code

 

 

 

以上是关于原生js上传图片遇到的坑的主要内容,如果未能解决你的问题,请参考以下文章

ajax 上传图片遇到的坑

原生JS,前端压缩图片方案

原生Js图片上传

[原创]SpringBoot上传图片踩的坑

纯原生js移动端图片压缩上传插件

原生 js 上传图片