跟我一起,利用bitcms内容管理系统从0到1学习小程序开发:三、上传图片到服务器

上一篇跟我一起,利用bitcms内容管理系统从0到1学习小程序开发:二、与服务端通信,Hello bitcms!被园子管理员人从首页撤下,理由是“原创精品,排版整齐,有足够的篇幅,与程序员相关,能够让读者从中学到知识”,经过认真深刻的反省,文章确实存在很多问题。

1、排版不够认真。周五下班前匆匆赶稿,只对内容进行简单的加粗换行。就勿勿发表了,确实排版不够精细。

2、原创必须的,但不够精品。内容是有大量的代码段,没有细化分解,阅读起来确实费劲。

3、作为程序员是代码写的多,但文字内容确实写的少,内容生涩是难免的。但我保证,文章里的每段代码都是经过推敲,测试过的。保证不了万全,但一定能调试成功。

问题多多,用心对待吧。再难,也要坚持把《利用bitcms内容管理系统从0到1学习小程序开发》系列文章写完。

一、微信小程序接口

上篇利用wx.request(OBJECT) 服务器进行通信,今天就利用wx.chooseImage(OBJECT)wx.uploadFile(OBJECT)两个接口配合着进行图片上传。

上传使用图片,必须先选择图片。小程序官方API给的图片选择接口wx.chooseImage(OBJECT),object参数表如下

上传接口wx.uploadFile(OBJECT),object参数表如下

对比下两个接口的参数,选择图片接口wx.chooseImage最多允许选择9张图片,而wx.uploadFile的参数filePath是string类型,最多只能上传一张图片。所以,多图片上传时是应注意,对选择图片参数tempFilePaths循环调用wx.uploadFile上传接口上传图片

1、添加小程序页面 pages/upload/upload

下面是单张图片上传例子

在upload.wxml页面中添加一个按钮,一个图片容器和进度条,代码如下

<button bindtap='chooseImage'>选择单张图片</button>
<view>
<image src='{{image}}' mode='aspectFit'></image>
<slider max='100' min='0' value='{{percent}}'  disabled='disabled'></slider>
</view>

界面预览

2、 页面的初始数据

  data: {
    image: '',//图片地址
    percent: 0,//上传进度
  },

3、图片选择按钮绑定事件chooseImage

/**单张图片 */
  chooseImage: function () {
    var that = this;
    wx.chooseImage({//使用图片选择接口
      count: 1,//图片数量
      sizeType: ['compressed'], //original 原图,compressed 压缩图,默认二者都有
      success: function (res) 
      {
        //图片选择后执行的代码
      }
    });
  }    

参数count:1可选图片个数是1个, sizeType,可以是['compressed'],['original']或['original'],'compressed']

4、上传接口wx.uploadFile集成

/* 向服务器请求或提交数据
parms 为小程序请求对象参数
success为请求成功后的回调数据
fail为请求失败后的回调数据
*/
var uploadFile = function (parms, success, fail) {
  if (!(typeof (parms) == 'object' && parms.url)) {//parms必须为object格式类型数据,且必须提供url属性
    if (typeof (fail) == 'function') {
      fail({ error: 1, message: '通信错误' });
    } else {
      throw Error('参数错误');
    }
  }
  //提交请求
  return wx.uploadFile(utils.extend({
    formData: setparms(parms.formData),
    complete: function (res) {
      turnResult(res, success, fail);
    }
  }, parms));
};

 参数 parms为小程序接口wx.uploadFile的Object参数,其它url为必填参数

下面为url参数判断代码,如果没有填写,就调用失败函数或抛出异常。

  if (!(typeof (parms) == 'object' && parms.url)) {//parms必须为object格式类型数据,且必须提供url属性
    if (typeof (fail) == 'function') {
      fail({ error: 1, message: '通信错误' });
    } else {
      throw Error('参数错误');
    }
  }
utils.extend(ojbect,object),为JSON对象合并函数。下面为实现代码
//json数据合并
var extend = function (target, source) {
  for (var p in source) {
    if (source.hasOwnProperty(p)) {
      target[p] = source[p];
    }
  }
  return target;
};
 setparms(object),功能主要有
A、为服务请求参数的字符型数据进行
encodeURIComponent编码,防止参数中有html,js等代码让服务器接收参数抛出异常。
B、为请求参数加个appid,时间戳、随机数和服务器请求数据签名。
/**处理请求参数 */
var setparms = function (data) {
  data = data ? data : {};
  var keys = Object.keys(data);
  var i = 0;
  for (i in keys) {
    if (typeof (data[keys[i]]) == 'string') {//encodeURI 防止提交html,js等代码,服务器出错
      data[keys[i]] = encodeURIComponent(data[keys[i]]);
    }
  };
  //提交数据,添加paddid,时间戳,随机数
  utils.extend(data, {
    appid: appId,
    timestamp: utils.timestamp(),
    nonce: utils.random()
  });

  //sign签名
  utils.extend(data, {
    sign: getSign(data)
  });
  return data;
};
 getSign(object)为签名算法函数,实现过程为各请求参数和秘钥appsecret(小写)按字母顺序排序后进行md5加密。 实现代码如下
/**获取签名 */
var getSign = function (parms) {
  var sortparms = '';
  if (parms && typeof (parms) == 'object') {
    var keys = Object.keys(parms);
    keys.push('appsecret');//appsecret不作为参数向服务器提交
    keys.sort();
    var i = 0;
    for (i in keys) {
      var val = parms[keys[i]] == undefined ? '' : parms[keys[i]] + '';
      if (keys[i] == 'appsecret') {
        val = appSecret;
      }
      if (val != '') {
        if (sortparms.length > 0) {
          sortparms += '&';
        }
        sortparms += keys[i] + '=' + val;
      }
    }
  }
  //md5加密
  return md5(sortparms);
};

turnResult(res, success, fail);
接口调用成功或失败后执行的代码
//返回数据处理
var turnResult = function (res, success, fail) {
  var data = {};
  if (res.statusCode == 200 && typeof (res.data) == 'object') {
    data = res.data;
  } else {
    if (typeof (res.data) == 'string' && res.data.indexOf('{') == 0) {
      data = JSON.parse(res.data);
    } else {
      data = { error: 1, message: res.data };
    }
  }
  var data = res.data;
  if (typeof (data) == 'string') {
    if (data.indexOf('{') == 0) {//为json数据
      data = JSON.parse(data);
    } else {
      data = { error: 1, message: data };
    }
  }
  if (data && data.error == 0) {
    if (typeof (success) == 'function') {
      if (data) {
        success(data);
      } else {
        success();
      }
    } else {
      var msg = res.message || '成功';
      wx.showToast({
        title: msg,
        icon: 'success',
        duration: 2000
      });
    }
  } else {
    data = data || { error: 1, message: '通信错误' };
    if (typeof (fail) == 'function') {
      fail(data);
    } else {
      wx.showToast({
        image: '/images/icon/error.png',
        title: data.message || '请求失败',
        duration: 2000
      });
    };
  }
};

上篇文章与服务器通信中的函数都有改动,如果您看了,请按照这篇文章中的函数进行更新。

图片选择按钮绑定事件chooseImage图片选择成功后,完整的代码如下

/**单张图片 */
  chooseImage: function () {
    var that = this;
    wx.chooseImage({//使用图片选择接口
      count: 1,//图片数量
      sizeType: ['compressed'], //original 原图,compressed 压缩图,默认二者都有
      success: function (res) 
      {//图片选择后执行的代码
        that.setData({ image: res.tempFilePaths[0] });
        let uploadTask = api.uploadFile({
          url: api.url.upload, //仅为示例,非真实的接口地址
          filePath: res.tempFilePaths[0],
          name: 'file',
          formData: {
            'folder': 'test',
            'watermark': 1
          }
        }, function (result) {
          if (result.error == 0) {
            that.setData({ image: result.data });
          };
        }, function (result) {
          that.setData({ image: '' });
        });
        uploadTask.onProgressUpdate((res) => {
          that.setData({ percent: res.progress });
        });
      }
    });
  }

二、服务器接口

1、服务器接口主要实现接收数据和图片保存。接收的参数有folder图片保存文件夹和watermark图片是否加水印

/// <summary>
        /// 上传
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult upload(string folder, int watermark)
        {
            var files = this.Request.Files;
            var path = "";
            Entity.AttachmentInfo attachmentInfo = null;
            if (files.Count > 0)
            {
                try
                {
                    Common.Upload uploadFile = new Common.Upload();
                    attachmentInfo = uploadFile.save(folder, files.Get(0), watermark == 1);
                    path = attachmentInfo.Path;
                }
                catch (Exception ex)
                {
                    return getResult(bitcms.Entity.Error.错误, ex.ToString());
                }
            }
            return getResult(bitcms.Entity.Error.请求成功, "上传成功", string.Format("{0}{1}", this.config.SiteDomain, Utils.trimStart(path, "/")));
        }

三、源码下载

源码中包含多张图片上传,下载地址 https://pan.baidu.com/s/1qZU4WgO 密码:sojk

四、小记

1、如何跳过域名校验

在微信开发者工具中,可以临时开启 开发环境不校验请求域名、TLS版本及HTTPS证书 选项,跳过服务器域名的校验。此时,在微信开发者工具中及手机开启调试模式时,不会进行服务器域名的校验。

就是在开发过程中,可以不使用ssl配置测试地址。微信开发者工具可做如下设置


感谢您的阅读。如果觉得有用的就请各位大神高抬贵手“推荐一下”吧!你的精神支持是博主强大的写作动力。

作者:逐月 《bitcms内容管理系统》开源系统  网站地址:www.bitcms.net

由于博主的水平有限,不足和错误之处在所难免,希望大家能够批评指出。

本文版权归作者和博客园所有,欢迎转载,但未经作者同意,必须保留此段声明,且在文章页面醒目位置显示原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/zhuyue/p/8317145.html