• 微信小程序开发(一) 微信登录流程, 这次介绍下小程序当中常用的图片上传。 前几天做了图片上传功能,被坑了一下。接下来我们来看一下微信上传api。这里的filePath就是图片的存储路径,类型居然是个St

    文/YXJ
    地址:http://blog.csdn.net/sk719887916/article/details/54312573

    上次介绍了小程序开发中的微信登录。文章:
    微信小程序开发(一) 微信登录流程

    这次介绍下小程序当中常用的图片上传。
    下篇:
    微信小程序开发(三) 微信小程序授权获取用户信息openid
    https://tamic.blog.csdn.net/article/details/89284104

    前几天做了图片上传功能,被坑了一下。接下来我们来看一下微信的上传api。

    这里写图片描述

    这里的filePath就是图片的存储路径,类型居然是个String,也就是 只能每次传一张图片,我以前的接口都是接收一个array,我本人又是一个半吊子的php,只能自己去改接收图片的接口。

    看一下页面效果图

    这里写图片描述

    一个很常见的修改头像效果,选择图片(拍照),然后上传。

    下面就是贴代码了

    ###首先是小程序的wxml代码###


    {{logo}}

    昵称



    宝宝性别





    宝宝年龄



    保存


    css代码我就不贴了,一些样式而已。

    ###对应的JS代码 ###
    var util = require(’…/…/…/utils/util.js’)
    var app = getApp()
    Page({
    data: {
    sex_items: [
    {name:‘1’, value:‘小王子’},
    {name:‘2’, value:‘小公主’},
    {name:‘0’, value:‘尚无’}
    ],
    logo:null,

    userInfo: {}
      },
    
    	 //事件处理函数
      bindViewTap: function() {
    wx.navigateTo({
      // url: '../logs/logs'
    //   url: '../load/load'
    })
      },
      onLoad: function () {
    console.log('onLoad')
    var that = this
    //调用应用实例的方法获取全局数据
    app.getUserInfo(function(userInfo){
      //更新数据
      console.log(userInfo);
      that.setData({
        userInfo:userInfo,
        logo:userInfo.logo
      })
    })
      },
    
      bindSaveTap: function(e){
    console.log(e)
    var formData = {
      uid:util.getUserID(),
      user_name:e.detail.value.nick_name,
      baby_sex:e.detail.value.baby_sex,
      baby_age:e.detail.value.baby_age
    }
     console.log(formData)
    app.apiFunc.upload_file(app.apiUrl.modify_user, this.data.logo, 'photos', formData, 
    function(res){
      console.log(res);
    },
    function(){
    })
      },  
    
      chooseImageTap: function(){
    let _this = this;
    wx.showActionSheet({
      itemList: ['从相册中选择', '拍照'],
      itemColor: "#f7982a",
      success: function(res) {
        if (!res.cancel) {
          if(res.tapIndex == 0){
            _this.chooseWxImage('album')
          }else if(res.tapIndex == 1){
            _this.chooseWxImage('camera')
          }
        }
      }
    })
    
      },
    chooseWxImage:function(type){
    let _this = this;
    wx.chooseImage({
      sizeType: ['original', 'compressed'],
      sourceType: [type],
      success: function (res) {
        console.log(res);
        _this.setData({
          logo: res.tempFilePaths[0],
        })
      }
     })
      }
    })
    

    主要讲解一下JS代码

    1、chooseImageTap方法
    用来显示一个选择图片和拍照的弹窗,用到了微信的一个页面交互的api showActionSheet,点击查看详细使用
    显示操作菜单

    2、chooseWxImage方法
    主要是用来选择图片以及接收图片路径回调的监听,点击查看详细使用
    从本地相册选择图片或使用相机拍照

    3、上传
    在chooseWxImage方法的success回调中我们可以看到,我把返回的图片路径res.tempFilePaths[0] 赋值给了logo,下面我们只需要调用upload方法就ok了,微信的uploadFile方法被我封装了一下变成了upload_file。

    ####uploadFile方法 ####
    //上传文件
    function upload_file(url, filePath, name, formData, success, fail) {
    console.log(‘a=’+filePath)
    wx.uploadFile({
    url: rootUrl + url,
    filePath:filePath,
    name:name,
    header: {
    ‘content-type’:‘multipart/form-data’
    }, // 设置请求的 header
    formData: formData, // HTTP 请求中其他额外的 form data
    success: function(res){
    console.log(res);
    if(res.statusCode ==200 && !res.data.result_code){
    typeof success == “function” && success(res.data);
    }else{
    typeof fail == “function” && fail(res);
    }
    },
    fail: function(res) {
    console.log(res);
    typeof fail == “function” && fail(res);
    }
    })
    }
    filePath就是upload_file中我们传进来的logo变量,也就是图片的绝对路径。

    ###服务器的接收图片代码###
    看过我上篇文章登录流程的文章的都熟悉了我服务器用的是php框架是Laravel。

    这里我只贴一下接收image的代码;

     if(!empty($_FILES['photos'])){
                        $up_arr['logo'] = upload_logo('photos','manage/images/user','logo',$user_id,0);
                        $up_arr['logo'] = $up_arr['logo'][0];
                        $user_info['logo'] = $Server_Http_Path . $up_arr['logo'];
       }
    

    核心方法在upload_log中。

    ####图片接收保存####
    if( !function_exists(‘upload_logo’)){
    function upload_logo( $key_name=‘photos’, $logo_path=‘manage/images/nurse’, $pre_name=‘logo’, salt=′20160101′,salt='20160101',salt=20160101,encode = 1,$make=0 ){
    $result_arr = array();
    global ServerHttpPath,Server_Http_Path,ServerHttpPath,App_Error_Conf;
    //分文件夹保存
    $date_info = getdate();
    $year = $date_info[‘year’];
    $mon = $date_info[‘mon’];
    $day = $date_info[‘mday’];
    logopath=sprintf("logo_path = sprintf("%s/%s/%s/%s",logopath=sprintf("logo_path,year,year,year,mon,day);if(!isdir(day); if(!is_dir(day);if(!isdir(logo_path)){
    res=mkdir(res=mkdir(res=mkdir(logo_path,0777,true);
    }
    //图片上传
    //foreach($photos as $key => $photo ){
    $photo = $_FILES[‘photos’];
    $name = $key_name;

                $file_id = Input::file($name);
                if(!empty($file_id) && $file_id -> isValid()){
                        $entension = $file_id -> getClientOriginalExtension();
                        if($pre_name == 'baby'){
                                $new_name = $pre_name . "_" . intval($salt) ."_" .time() . "_" . salt_rand(2,2);
                        }else {
                                $new_name = $pre_name . "_" . intval($salt) ."_" . salt_rand(2,2);
                        }
                        $path_id = $file_id -> move($logo_path,$new_name."_b.".$entension);
                        if(!empty($path_id)){
                                $path_name = $path_id->getPathName();
                                $image_size=getimagesize($path_name);
     $weight=$image_size["0"];//
     $height=$image_size["1"];
     ///获取图片的高
     $photo_info['url']    = $path_name;                                            
     $photo_info['width']  = $weight;
     $photo_info['height'] = $height;
     $result_arr[] = $photo_info;
          }else{
         $result_arr[] = $path_name;
       }  
    //处理图片
    if($make == 1){
     $img = Image::make($path_name)->resize(200, $height*200/$weight);
    $img->save($logo_path ."/".$new_name."_s.".$entension);
       //dd($img);
      //  return $img->response('jpg');
                                }
                        }
    if(empty($result_arr)){
     $response['result_code'] = -1006;
       $response['result_msg'] = $App_Error_Conf[-1006];
             return response($response);
                        }
     if($encode == 1){
                                $result_arr = json_encode($result_arr);
                        }
                }
                return $result_arr;
         }
       }
    

    这个代码格式真的很烦人啊,我就大概整理了一下。

    这样我们就入门了小程序图片上传和接口功能了。

    系列文章:
    微信小程序开发(一) 微信登录流程
    http://blog.csdn.net/sk719887916/article/details/53761107
    微信小程序开发(二)图片上传+服务端接收
    微信小程序开发(三) 微信小程序授权获取用户信息openid
    https://tamic.blog.csdn.net/article/details/89284104

    第一时间获取技术文章请关注微信公众号!

    开发者技术前线

    展开全文
  • 当然小程序也是可以上传图片的,微信小程序文档也写的很清楚。上传图片 首先选择图片 通过wx.chooseImage(OBJECT)实现官方示例代码wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], /...

    几乎每个程序都需要用到图片。
    在小程序中我们可以通过image组件显示图片。

    当然小程序也是可以上传图片的,微信小程序文档也写的很清楚。

    上传图片

    首先选择图片

    通过wx.chooseImage(OBJECT)实现

    官方示例代码

    wx.chooseImage({
      count: 1, // 默认9
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        var tempFilePaths = res.tempFilePaths
      }
    })

    图片最多可以选择9张, 也可以通过拍摄照片实现,当选择完图片之后会获取到图片路径, 这个路径在本次启动期间有效。
    如果需要保存就需要用wx.saveFile(OBJECT)

    上传图片

    通过wx.uploadFile(OBJECT) 可以将本地资源文件上传到服务器。

    原理就是客户端发起一个 HTTPS POST 请求,其中 content-type为 multipart/form-data。

    官方示例代码

    wx.chooseImage({
      success: function(res) {
        var tempFilePaths = res.tempFilePaths
        wx.uploadFile({
          url: 'http://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
          filePath: tempFilePaths[0],
          name: 'file',
          formData:{
            'user': 'test'
          },
          success: function(res){
            var data = res.data
            //do something
          }
        })
      }
    })

    示例代码

    看完了官方文档, 写一个上传图片就没有那么麻烦了,下面是真实场景的代码

    import constant from '../../common/constant';
    Page({
      data: {
        src: "../../image/photo.png",  //绑定image组件的src
         //略...
      },
      onLoad: function (options) {
          //略... 
      },
      uploadPhoto() {
        var that = this; 
        wx.chooseImage({
          count: 1, // 默认9
          sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
          sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
          success: function (res) {
            // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
            var tempFilePaths = res.tempFilePaths;
            upload(that, tempFilePaths);
          }
        })
      }
    })
    
    function upload(page, path) {
      wx.showToast({
        icon: "loading",
        title: "正在上传"
      }),
        wx.uploadFile({
          url: constant.SERVER_URL + "/FileUploadServlet",
          filePath: path[0], 
          name: 'file',
          header: { "Content-Type": "multipart/form-data" },
          formData: {
            //和服务器约定的token, 一般也可以放在header中
            'session_token': wx.getStorageSync('session_token')
          },
          success: function (res) {
            console.log(res);
            if (res.statusCode != 200) { 
              wx.showModal({
                title: '提示',
                content: '上传失败',
                showCancel: false
              })
              return;
            }
            var data = res.data
            page.setData({  //上传成功修改显示头像
              src: path[0]
            })
          },
          fail: function (e) {
            console.log(e);
            wx.showModal({
              title: '提示',
              content: '上传失败',
              showCancel: false
            })
          },
          complete: function () {
            wx.hideToast();  //隐藏Toast
          }
        })
    }

    后端代码

    后端是用java写的,一开始的时候,后端开始用了一些框架接收上传的图片,出现了各种问题,后来使用了纯粹的Servlet就没有了问题, 把代码贴出来省的以后麻烦了。

    注意: 代码使用了公司内部的框架,建议修改后再使用

    public class FileUploadServlet extends HttpServlet {
    
        private static final long serialVersionUID = 1L;
        private static Logger logger = LoggerFactory.getLogger(FileUploadServlet.class);
    
        public FileUploadServlet() {
            super();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            JsonMessage<Object> message = new JsonMessage<Object>();
            EOSResponse eosResponse = null;
            String sessionToken = null;
            FileItem file = null;
            InputStream in = null;
            ByteArrayOutputStream swapStream1 = null;
            try {
                request.setCharacterEncoding("UTF-8"); 
    
                //1、创建一个DiskFileItemFactory工厂  
                DiskFileItemFactory factory = new DiskFileItemFactory();  
                //2、创建一个文件上传解析器  
                ServletFileUpload upload = new ServletFileUpload(factory);
    
                //解决上传文件名的中文乱码  
                upload.setHeaderEncoding("UTF-8");   
                // 1. 得到 FileItem 的集合 items  
                List<FileItem> items = upload.parseRequest(request);
                logger.info("items:{}", items.size());
                // 2. 遍历 items:  
                for (FileItem item : items) {  
                    String name = item.getFieldName();  
                    logger.info("fieldName:{}", name);
                    // 若是一个一般的表单域, 打印信息  
                    if (item.isFormField()) {  
                        String value = item.getString("utf-8");  
                        if("session_token".equals(name)){
                            sessionToken = value;
                        }
                    }else {
                        if("file".equals(name)){
                            file = item;
                        }
                    }  
                }
                //session校验
                if(StringUtils.isEmpty(sessionToken)){
                    message.setStatus(StatusCodeConstant.SESSION_TOKEN_TIME_OUT);
                    message.setErrorMsg(StatusCodeConstant.SESSION_TOKEN_TIME_OUT_MSG);
                }
                String userId = RedisUtils.hget(sessionToken,"userId");
                logger.info("userId:{}", userId);
                if(StringUtils.isEmpty(userId)){
                    message.setStatus(StatusCodeConstant.SESSION_TOKEN_TIME_OUT);
                    message.setErrorMsg(StatusCodeConstant.SESSION_TOKEN_TIME_OUT_MSG);
                }
                //上传文件
                if(file == null){
                }else{
                    swapStream1 = new ByteArrayOutputStream();
    
                    in = file.getInputStream();
                    byte[] buff = new byte[1024];
                    int rc = 0;
                    while ((rc = in.read(buff)) > 0) {
                        swapStream1.write(buff, 0, rc);
                    }
    
                    Usr usr = new Usr();
                    usr.setObjectId(Integer.parseInt(userId));
    
                    final byte[] bytes = swapStream1.toByteArray();
    
                    eosResponse= ServerProxy.getSharedInstance().saveHeadPortrait(usr, new RequestOperation() {
    
                        @Override
                        public void addValueToRequest(EOSRequest request) {
                            request.addMedia("head_icon_media", new EOSMediaData(EOSMediaData.MEDIA_TYPE_IMAGE_JPEG, bytes));
                        }
                    });
    
                    // 请求成功的场合
                    if (eosResponse.getCode() == 0) {
                        message.setStatus(ConstantUnit.SUCCESS);
                    } else {
                        message.setStatus(String.valueOf(eosResponse.getCode()));
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally{
                try {
                    if(swapStream1 != null){
                        swapStream1.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if(in != null){
                        in.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            PrintWriter out = response.getWriter();  
            out.write(JSONObject.toJSONString(message));  
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    
    }

    更多精彩请关注微信公众账号likeDev
    这里写图片描述

    展开全文
  • 本文原地址:http://www.php.cn/xiaochengxu-353507.html最近有很多网友私信问我们网站上下载的那些小程序源码,怎么将它导入到小程序开发者工具中呢?因为问的人太多,今天就统一整理文章与大家分享,希望大家以后...

    最近有很多网友私信问我们网站上下载的那些小程序源码,怎么将它导入到小程序开发者工具中呢?因为问的人太多,今天就统一整理文章与大家分享,希望大家以后针对这个问题就不要再私信问我了。

    1:安装后图标:

    微信官方开发者工具如何导入小程序源码demo

    登录,随意一个微信号,扫描后即可登录

    2:选择无appleid;项目名称随意,地址选择下载好的demo文件夹

    微信官方开发者工具如何导入小程序源码demo

    注意,假如看不到效果,或者跳出这个错误

    微信官方开发者工具如何导入小程序源码demo

    有可能是项目目录选择错误了,要选择app.json文件的根目录导入(一般导致上面的错误,都是选择了其上级文件夹)

    微信官方开发者工具如何导入小程序源码demo

    比如,以下文件夹目录,需要导入红线框内的目录才是正确的目录:

    微信官方开发者工具如何导入小程序源码demo

    3:点击添加项目,即可看到项目

    微信官方开发者工具如何导入小程序源码demo

    4:删除项目

    微信官方开发者工具如何导入小程序源码demo


    展开全文
  • 微信开发者工具使用教程 如何上传、发布、审核等 2020年3月31日录 - 微信开发者工具使用教程 01-微信开发者工具的下载和安装 02-微信小程序账号的注册、登录、appid的获取 03-微信小程序开发和公众号开发模式的切换 ...
  • 前端靠微信后端靠小白! 话不多说 源码如下https://github.com/WillFang1997/Code 1.下载好源码之后需配置服务器域名,已配置过的可以跳过。 首先,需要登录微信公众号平台,进入:设置 - 开发设...

    众所周知,小程序搭配小白接口简直就是BUG一样的存在。不花一分钱就能发布自己的专属小程序。免费套餐强大到足以支撑一个私人小应用啦。 可免费调用15万次/月真的是很良心了。

    前端靠微信,后端靠小白!

    话不多说 源码如下https://github.com/xiaoren-yesapi/yesapi-miniprogram-1

    1.下载好源码之后需配置服务器域名,已配置过的可以跳过这一步。

    首先,需要登录微信公众号平台,进入:设置 - 开发设置 - 服务器域名,修改request合法域名,uploadFile合法域名,修改为你当前所在的小白接口域名。小白接口已支持HTTPS访问。如下:
    在这里插入图片描述

    特别注意!在微信服务器域名配置request合法域名时,一定要注意,域名前后不能有空格,最后不能有斜杠!!
    否则会出现类似以下的错误提示:
    在这里插入图片描述
    如果不清楚自己所在的域名,可登录小白开放平台,进入:系统设置 - 我的套餐,查看接口域名。如:
    在这里插入图片描述
    2.配置好之后用微信小程序开发者工具打开源码
    在这里插入图片描述
    点击授权登录后会看的以下页面
    在这里插入图片描述
    接下来做一步十分重要的操作,打开根目录下的app.js拉到下面,把okayapiHost,okayApiAppKey,okayApiAppSecrect填写成自己的信息,在系统设置 - 我的套餐查看,记得是https不是http
    在这里插入图片描述
    现在离完成整个部署只差填充后端数据了!
    打开源代码目录下CSV文件夹里modelBulid.csv。查看该程序需要的六个模型并添加相应字段。
    在这里插入图片描述
    在这里插入图片描述
    现在带大家建第一个模型tea_swiper
    在这里插入图片描述
    之后在我的模型数据内找到模型点击管管模型并加入modelBuild.csv文件内的字段名称/类型/备注
    在这里插入图片描述
    在这里插入图片描述
    然后添加数据,如无想放在轮播图的照片可以按照tea_swiper.csv内的地址添加。添加后效果如图。
    在这里插入图片描述
    接下来点击开发者工具-编译,即可看到轮播图已经成功调用啦!!!(您的小程序已经成功调用出放在小白数据库的数据了)
    在这里插入图片描述
    细心的同学会发现tea_user里面也已经拿到了登录的人的微信昵称以及openID,新用户登录这个小程序并且授权,就会新增一条数据。(微信的openID是微信用户唯一标识符,如有需求也可以增加省份,语言,用户头像等字段记录用户信息,调整模型跟pages/login.js代码即可)
    在这里插入图片描述
    接下来根据CSV文件夹里的tea.csv按操作添加相应的数据即可拥有自己的小程序啦(小白会员可直接用该csv文件导入到数据库哦(疯狂暗示)),tea_user,tea_order,tea_shopcar以及tea_moment都不用添加数据,下订单,发朋友圈等操作会自动添加。最终效果如下。在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
    开源不易,需要鼓励。您的支持就是我们最大的前进动力!

    展开全文
  • 【AI番外】今天说微信小程序开发,不能上线的AI,都是纸老虎 训练好一个深度学习模型之后,必须要将其部署到生产环境当中,才能产生真正的价值,为更多的用户所体验。 部署到线上现在最轻便且最方便传播的当属...

    文章首发于微信公众号《有三AI》

    【AI番外】今天说微信小程序开发,不能上线的AI,都是纸老虎

    训练好一个深度学习模型之后,必须要将其部署到生产环境当中,才能产生真正的价值,为更多的用户所体验。

    部署到线上现在最轻便且最方便传播的当属微信小程序了,微信小程序依托于微信,不需要下载安装即可使用,用户扫一扫或搜一下即可打开应用。

    腾讯官方已经宣布微信小程序的数量超过了app,对于我们个人来说,只要准备好https服务,就可以比较方便的开发。

    下面我们就讲讲微信小程序前端开发和服务端开发。

    “这年头,什么都的会”

     

    01 前端开发

    微信小程序前端开发与网页的开发有非常多共通的技术,但是也有它独特的特点,比如微信小程序的前端工具等。这一小节从微信小程序的技术特点,工具的使用,小程序的通用目录配置等各个方面来详细讲述前端的开发流程。

    1.1 小程序简介

    小程序一般都指微信小程序,是嵌入到微信APP里面的一种伪原生的方式,”无需安装就可运行”,当前小程序包的上限已经扩展到了8M。

    如图是微信小程序《言有三工作室》和其AI摄影菜单的主界面。

     

     

    相对于微信APP,小程序有几个重要的优势,分别可以从用户和开发者的角度来看。

    从用户角度来看:

    (1) 使用便捷,简单方便,不需要安装额外APP,节省内存。

    (2) 安全,小程序经过微信严格筛选,相比于APP,不容易存在病毒、信息泄露、诈骗等情况的出现。

    从开发者角度:

    (1) 降低了开发门槛,缩短了开发周期。一款成熟的APP需要适配IOS,Android两大平台,各自都有非常庞大的生态体系,而小程序只需要基于微信的生态环境开发就可以实现共用。

    (2) 微信庞大的用户基数给小程序带来了流量优势,相比于APP的推广更加容易。传播方便,扫二维码即可体验。

    1.2 小程序开发工具

    以Mac上的小程序开发工具为例,下载链接在这里,https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

    打开咱们自己的小程序,体验一下页面。

    上面工具有一些重要的选项。

    (1) 编译,顾名思义就是用于编译小程序代码。

    (2) 扫码,用于生成二维码在手机上体验。

    (3) 提交版本,用于将代码提交到后台,这样拥有体验权限的用户就可以在小程序没有正式发布之前就能体验。另外,也用于正式版本的提交与发布。

    以上就是小程序常用的选项,另外在开发的过程中经常需要与后台进行交互,这时就需要在小程序开发工具和后台同时进行debug,使用起来也非常的方便。

    1.3 小程序前端目录

    熟悉了工具后,我们来仔细审视一下如何开发小程序。我们先看看微信小程序的项目路径。

    1.工程目录

    包含目录为images,pages,另包含文件app.json,app.js,app.wxss,project.config.json。

    (1) image,存储小程序本地使用的一些图。一般是页面的缩略图,log日志等。这里不适合放较多的图和较大的图,因为小程序本身有大小限制,最新的标准是整个小程序所有分包大小不超过8M,单个分包/主包大小不能超过 2M。

    (2) pages,包含小程序所有功能页面的配置。

    (3) app.js,包含程序的主流程代码,我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。它可以是空的,但是必须存在,它通常会包含以下函数。

    onLaunch函数,用于监听小程序的初始化,全局只触发一次,因此,可以在这里加载一些默认变量。

    onShow函数,用于监听小程序显示,小程序的启动,从后台重新回到前台也会触发它。顾名思义,我们常常在这里对一些图片文字进行显示。

    OnHide函数,是小程序从前台到后台的触发函数。

    除了这3个函数之外,我们可以在js脚本里面任意添加函数,将其注册到Object参数中,就可以用this进行访问了。通常与服务端的数据交互与手机本地的文件访问,都是另外定义函数。

    小程序启动之后,在app.js定义的App实例的onLaunch回调会被执行:

    App({

      onLaunch: function () {

        // 小程序启动之后 触发

      }

    })

    整个小程序只有一个App实例,是全部页面共享的,然后就可以进入pages目录了。

    (4) app.json 是对当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部tab等,一个示例配置如下。

    {

      "pages":[

        "pages/index/index",

        "pages/logs/logs"

      ],

      "window":{

        "backgroundTextStyle":"light",

        "navigationBarBackgroundColor": "#fff",

        "navigationBarTitleText": "WeChat",

        "navigationBarTextStyle":"black"

      }

    }

    pages用于描述当前小程序所有页面路径,这是为了让微信客户端知道当前你的小程序页面定义在哪个目录。Window定义里小程序所有页面的顶部背景颜色,文字颜色等。

    (5) 工具配置 project.config.json

    通常大家在使用一个工具的时候,都会针对各自喜好做一些个性化配置,例如界面颜色、编译配置等,当你换了另外一台电脑重新安装工具的时候,你还要重新配置。考虑到这点,小程序开发者工具在每个项目的根目录都会生成一个project.config.json,你在工具上做的任何配置都会写入到这个文件,当你重新安装工具或者换电脑工作时,你只要载入同一个项目的代码包,开发者工具就自动会帮你恢复到当时你开发项目时的个性化配置,其中会包括编辑器的颜色、代码上传时自动压缩等一系列选项。

    2. Pages目录

    pages,是我们小程序开发的主要工作目录,它包含以下文件。

    js,即JavaScrip文件。

    json,即项目配置文件,负责窗口颜色等。

    wxml,类似HTML文件。

    wxss,类似CSS文件。

    这4个文件一起组成一个页面。

    (1) wxss文件是css样式文件。最底层的样式,比如整个页面的背景颜色等,可以在这里配置,wxss文件可以没有。wxss具有css大部分的特性,小程序在wxss也做了一些扩充和修改。比如新增了尺寸单位,在写css样式时,开发者需要考虑到手机设备的屏幕会有不同的宽度和设备像素比,采用一些技巧来换算一些像素单位。wxss在底层支持新的尺寸单位rpx,开发者可以免去换算的烦恼,只要交给小程序底层来换算即可,由于换算采用浮点数运算,所以运算结果会和预期结果有一点点偏差。

    (2) wxml文件是当前页面的配置文件,我们在这里定义整个页面中各个元素的排版,给一些控件绑定事件等,这个文件也可以没有。它和HTML非常相似,有标签、属性等构成,但是也有很多不一样的地方,比如标签名字有点不一样。写HTML的时候,经常会用到的标签是div,p,span,而小程序的wxml用的标签是view,button,text等,另外还多了一些wx:if这样的属性以及{{ }}这样的表达式,它可以把一个变量绑定到界面上,称之为数据绑定,非常有用。

    (3) json文件是项目配置文件,配置一些窗口颜色等等,笔者一般在app.json中配置,page中的文件留空。

    (4) js文件就是javascript页面逻辑文件。按钮的响应以及与后端的交互,都在这里处理。

    1.4 小程序前端开发

    下面我们开始正式开发,小程序的前端开发需要实现以下几个功能。(1)选择图片并展示。(2)提交图片到后台以及获取处理结果并展示。(3)保存相册结果与分享。

    我们以有三工作室的小程序为例。

    1 定义好样式文件

    我们这里实现3个页面的功能,第一个是ais页面,它在小程序主菜单中添加美学评分模块。

        在ais.wxml中添加如下代码

      <view>

      <button bindtap='aestheticscore'>

        <image src='../../image/building_score.jpg'></image>

        <image src='../../image/i1.png'></image>

        <text>美学评分</text>

      </button>

      </view>

    可知,在这里添加了缩略图,一个按钮,以及文本等属性,并绑定了函数aestheticscore,函数的定义如下,实现到aestheticscore页面的跳转。

      aestheticscore: function (e) {

        wx.navigateTo({

          url: '../aestheticscore/aestheticscore',

        })

      },

     

    最终的结果如上图。

    接下来第二步就是实现aestheticscore页面,我们先看一下整个页面的样式,如下图。

    包含了几个按钮和一个图像显示框,完整的wxml文件如下

    <!--pages/aestheticscore/aestheticscore.wxml-->

    <view>

      <image src='../../image/background.jpg'> </image>

      <image src='../../image/logo.jpg'></image>

      <view style='text-align:center;margin:20rpx;font-weight:600; font-family: "Microsoft Yahei";'>{{title}}</view>

      <view>

        <image wx:if="{{bgPic}}" src="{{bgPic}}" mode='widthFix'></image>

        <view wx:else></view>

      </view>

      <view>

        <button data-way="camera" bind:tap="chooseImage">使用相机</button>

        <button data-way="album" bind:tap="chooseImage">相册选择</button>

        <view>

          <button bindtap='back'>返回</button>

          <button bindtap='nextPage'>下一步</button>

        </view>

      </view>

    </view>

    在页面的顶端包含了一个背景image,一个logo image,一个text控件,是为了显示该页面的背景,小程序的logo,以及该页面的功能名字,并且功能名字{{title}}是从js文件中获取的。

    然后页面使用了一个container控件来保存所选择的图片,当有选择的图片的时候显示{{bgPic}},当没有的时候显示“emptyBg”。

    最后是若干个按钮,包括“使用相机”,“相册选择”两个选择不同图片来源的按钮,返回上一级菜单的“返回”按钮以及进入下一步的“下一步”按钮。

    第三个页面就是showaesthetic页面,它返回结果并显示,包含一个保存至当前目录和分享的按钮,按钮和显示图片的控件与第二个页面中的按钮的样式相同,这里多了一个显示结果,即下图美学分数“88.0495548248”的text控件,属性如下。

     <view style='text-align:center;margin:20rpx;font-weight:600; font-family: "Microsoft Yahei";'>{{text}}</view>

    以上就是界面的定义,分别实现进入菜单,选择图片并上传,获取结果并展示,接下来具体实现其中的功能。

    2 实现选择图片并显示的功能

    直接使用微信的官方API就可以实现选择图片并显示的功能,需要使用到chooseImage接口,代码如下:

      chooseImage(from) {

        wx.chooseImage({

          count: 1,

          sizeType: ["original", "compressed"], // 可以指定是原图还是压缩图,默认二者都有

          sourceType: [from.target.dataset.way],

          // sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 

          success: (res) => {

            var tempFilePaths = res.tempFilePaths;

            this.setData({

              bgPic: res.tempFilePaths[0]

            });

            this.assignPicChoosed();

          },

          fail: (res) => {

            this.assignPicChoosed();

          },

          complete: (res) => {

            this.assignPicChoosed();

          },

        })

      },

    3 实现提交图片到后台并获取返回结果的功能

    同样,直接使用微信的官方API即可,用到的函数是wx.uploadFile。

    //上传图片并获取结果

    nextPage: function (e) {

        var that = this;

        //将选择的图片作为全局数据

        app.globalData.bgPic = that.data.bgPic;

        wx.showToast({

          title: '正在处理', icon: 'loading', duration: 100000

        });

        wx.uploadFile({

          url: 'https://yanyousan.com/aestheticscore',

          filePath: that.data.bgPic,

          name: 'file',

          header: {

            'content-type': 'multipart/form-data'

          },

          success: function (res) {

            // console.log(res.data);

            wx.hideToast();

            if (res.statusCode == 200) {

              var jj = JSON.parse(res.data);//将json字符串转为json对象

              console.log('200');

              app.globalData.aestheticscore = jj["score"];

              console.log(app.globalData.aestheticscore);              

              wx.navigateTo({

                url: '../showaestheticscore/showaestheticscore',

              })

            } else {

              wx.showModal({

                title: '提示',

                content: '服务器错误,请稍后重试!',

              });

            }

          },

          fail: function (res) {

            console.log(res);

          }

        })

      },

    4 显示结果与分享

    上面已经定义好了显示的样式,并且将结果绑定到了app.globalData.aestheticscore中,所以在showaesthetic只需要获取到结果,通过onload函数实现,其中调用了getImageInfo函数。

      onLoad: function (options) {

        wx.getImageInfo({

          src: app.globalData.bgPic,

          text: app.globalData.aestheticscore,

          success: res => {

            this.bgPic = res.path

            console.log(res.width)

            console.log(res.height)

            console.log(app.globalData.aestheticscore)

          }

        }),

          this.setData({

            bgPic: app.globalData.bgPic,

            text: app.globalData.aestheticscore

          })

      },

    另外,这里还包括保存结果以及分享按钮,前者需要使用到saveImageToPhotosAlbum函数,后者即实现onShareAppMessage函数。

    savePic() {

        wx.getImageInfo({

          src: app.globalData.bgPic,

          success: function (res) {

            var path = res.path;

            wx.saveImageToPhotosAlbum({

              filePath: path,

              success(result) {

                console.log(result)

                wx.showToast({

                  title: "保存成功",

                  icon: 'success',

                  duration: 1000

                })

              }

            })

          }, fail(e) {

            console.log("err:" + e);

          }

        }),

        wx.navigateTo({

            url: '../ais/ais',

        })

      },

      onShareAppMessage: function () {

        return {

          title: "言有三工作室",

          path: "/pages/ais/ais",

          success: function (res) {

            // 转发成功

            console.log("转发成功:" + JSON.stringify(res));

            wx.showToast({

              title: "转发成功",

              icon: 'success',

              duration: 2000

            })

          },

          fail: function (res) {

            // 转发失败

            console.log("转发失败:" + JSON.stringify(res));

          }

        }

      }

    })

    前端开发的核心内容如上,主要就是定义好样式和相关的跳转逻辑。

     

    02 服务端开发

    上一节,我们说了微信小程序的前端开发,这一节我们就来完成服务端的开发。主要包括:(1)域名注册与证书申请。(2)Flask服务端框架介绍。(3)算法搭建与实现。

    2.1 域名注册与管理

    所谓域名就是我们熟知的网址了,它相比IP地址更加方便记忆,如www.yanyousan.com。域名注册有很多的渠道,国内可以到腾讯云等拥有域名服务的厂商处注册,只要选择的域名没有被注册就行。

    选择域名注册的时候有一些类型,需要简单了解。

    .com域名,是国际最广泛流行的通用域名格式,全球注册量超过1.1亿。.com域名一般用于商业性的机构或公司,任何人都可以注册。如果可以的话,我们尽量注册这个域名。

    .cn,中国使用的顶级通用域名,这是全球唯一由中国管理的国际顶级域名。com.cn属于.cn里面的分类,其他还有net.cn,org.cn,gov.cn等。

    .net是类别顶级域名,适用于各类网络提供商。

    .org是非营利性机构。

    .gov.cn是政府机构。

    我们尽量使用.com或者.cn。

    由于是微信小程序的开发,直接选择腾讯云很方便。https://cloud.tencent.com/

    注册得到域名之后,下一步就是进行域名备案,大陆的域名必须通过备案才能提供服务。至于备案的具体流程,根据官网的操作进行就可以了。

    备案完成之后,就可以去申请https服务了。实际上没有https,用http服务也是可以正常搭建网络访问的,但是微信小程序必须使用https协议。所以,我们需要去申请https证书。

    腾讯云提供了一年的免费证书,大家可以使用。

    2.2 服务端框架简介

    1.Web应用程序流程

    对于Web应用来说,当客户端想要获取动态资源时,就会发起一个HTTP请求,比如用浏览器访问一个URL,Web应用程序会在后台进行相应的业务处理,从数据库或者进行一些计算操作取出用户需要的数据,生成相应的HTTP响应。当然,如果访问静态资源,则直接返回资源即可,不需要进行业务处理。服务器要想对每个URL请求返回对应的结果,需要建立URL和函数之间的一一对应关系,这就是Web开发中所谓的路由分发。

    客户端接到响应后,必须显示给用户看。这个时候就需要一个视图函数,它可以返回简单字符串,也可以返回复杂的表单,然后在前端渲染。

    2.Flask服务端框架基础

    由于对python比较熟悉,我决定使用python作为服务端的web框架语言。python的web框架,有Django,Flask,Pyramid,Tornado,Bottle,Diesel,Pecan,Falcon等等。其中Flask、Pyramid和Django,是同时适合开发小项目和大型商业项目的框架。

    相对来说,Flask更适合面向需求简单的小应用,所以我们选择了Flask。

    Flask是一个微型的服务端框架,它旨在保持核心的简单,但同时又易于扩展。默认情况下,Flask不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask支持用扩展来给应用添加这些功能,众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask的这些特性,使得它在Web开发方面变得非常流行。

    既然如此简单,那我们就先看一个程序员必写的HelloWorld,7行Python代码就够了。

    # from http://flask.pocoo.org/ tutorial

    from flask import Flask

    app = Flask(__name__)

    @app.route("/")

    def hello():

        return "欢迎来到言有三工作室"

    if __name__ == "__main__":

        app.run()

    一个没什么Python web开发经验的人就可以很快的上手,我们看看上面都包含什么。

    from flask import Flask

    app = Flask(__name__)

    这就是用于创建一个程序实例,__name__变量就是程序主模块的名字。

    @app.route("/")

    def hello():

        return "欢迎来到言有三工作室"

    Flask底层使用werkzeug来做路由分发,上面的代码就是用于创建路由映射,@app.route就是程序实例提供的修饰器,它将hello函数注册为路由,而且是根地址的处理程序。所以,一旦我们打开https://yanyousan.com,就会显示该函数的结果,大家可以试试。

    if __name__ == "__main__":

        app.run()

    这就是主函数了,只有执行这个脚本后,才会启动开发web服务器。服务器启动后,进入轮询,等待并处理请求,直到程序停止。

    更多Flask的使用,我们就不一一说明,大家可以去参照官网http://flask.pocoo.org/学习。

    2.3 服务端开发

    下面开始服务端的开发,主要是实现表单,路由映射功能。

    1.目录划分

    部署服务时,我们应该先划分一下目录结构。根目录下包含,app,models,manager.py。

    manager.py是主文件入口,其中的内容如下:

    from app import app

    if __name__=='__main__':

        app.run(debug=True)

    app中存储代码文件和其他的一些资源文件如图片,models是我们专门用来保存模型的目录,因为这些文件一般比较大,不适合放在git中托管。app中包括static,utils,以及form.py,view.py等脚本。static存储的是一些静态文件,utils下面放置我们的算法模块,所有算法相关的代码就定义在这里。

    2 表单文件form.py

    表单即WebForm,它负责封装用于用户端显示的数据,充当了在视图及程序之间传输、处理数据的媒介,可以通过form.get("键名")的方式来读取这些数据,也可以通过form.set("属性名",值)来改变视图中传过来的数据值。

    每个Web表单都由一个继承自Form的类表示。这个类定义表单中的一组字段,每个字段都用对象表示。字段对象可附属一个或多个验证函数,它用来验证用户提交的输入值是否符合要求。

    因为我们是处理图片,所以需要定义图片的表单类,看下面代码。

    #coding=utf8

    from flask_wtf import FlaskForm

    from wtforms import FileField, SubmitField

    from wtforms.validators import DataRequired

    class PictureForm(FlaskForm):

        picture = FileField(

            label=u'图片',

            validators=[

                DataRequired(u'上传图片不能为空')

            ],

            render_kw={'accept': 'image/*', 'style': 'display:none', 'align': 'margin-top:10px'}

        )

        submit = SubmitField(

            u'提交',

            render_kw={'style': 'text-align: center; font-size:30px; margin-top:10px; margin-left:5px', 'align': 'center'}

        )

    它包含一个picture字段和一个submit按钮。Picture字段需要验证传输的图片不能为空,即表单验证。只要存在表单元素,基本就少不了表单验证。

    3. 路由映射view.py

    这个脚本主要用于与前端的交互,我们看一下例子,这就是上一节我们演示的美学评分的那个例子。

    #美学评分

    @app.route('/aestheticscore', methods=['GET', 'POST'])

    def get_aestheticscore():

        file_data = request.files['file']

        if file_data and allowed_file(file_data.filename):

            filename = secure_filename(file_data.filename)

            file_uuid = str(uuid.uuid4().hex)

            time_now = datetime.now()

            filename = time_now.strftime("%Y%m%d%H%M%S")+"_"+file_uuid+"_"+filename

            file_data.save(os.path.join(app.config['AESTHETICSCORE'], filename))

            src_path = os.path.join(app.config['AESTHETICSCORE'], filename)

            score = aestheticscore(src_path)

            if float(score) < 0:

            data = {

            "code": 0,

            "score": "请使用建筑图片"

           }

            else:

            data = {

            "code": 0,

            "score": str(score)

           }

          

            return jsonify(data)

        return jsonify({"code": 1, "msg": u"文件格式不允许"})

    看上面的代码,get_aestheticscore()是创建的路由函数,它接收前端上传的图,并调用aestheticscore函数进行处理,然后返回json格式的结果。aestheticscore就是我们实现算法的主函数了,这里不在本书的讲述内容,所以不做介绍。

    我们再回到前端中怎么和服务端进行交互,在前端的上传图片那里有以下代码。

    wx.uploadFile({

       url: 'https://yanyousan.com/aestheticscore',

       filePath: that.data.bgPic,

       name: 'file',

       header: {

         'content-type': 'multipart/form-data'

       },

       success: function (res) {

         // console.log(res.data);

         wx.hideToast();

         if (res.statusCode == 200) {

           var jj = JSON.parse(res.data);//将json字符串转为json对象

           console.log('200');

           app.globalData.aestheticscore = jj["score"];

           console.log(app.globalData.aestheticscore);              

           wx.navigateTo({

             url: '../showaestheticscore/showaestheticscore',

           })

         } else {

           wx.showModal({

             title: '提示',

             content: '服务器错误,请稍后重试!',

           });

         }

       },

    其中url: 'https://yanyousan.com/aestheticscore'就是我们上传图片的网址接口,var jj = JSON.parse(res.data)就是获取的json格式的返回结果,jj["score"]就是得到的分数。

    至此,我们就完成了上传图片,后台处理并返回结果。前后端的基本技术内容到此基本结束,感谢“有三AI学院实习生杨皓博”在1.1部分的分享

    如果大家想体验我们的功能,欢迎移步摄影公众号《有三工作室》与上面的小程序平台,有很多漂亮的小姐姐等你噢。

     

    更多请关注微信公众号《有三AI》与知乎《有三AI学院》。

    展开全文
  • 微信开发者工具中 实现微信小程序之相机拍照功能的开发 包括相机拍照文件相册的打开 镜头的反转等
  • 微信小程序商城(Java版) 技术选型 1 后端使用技术 1.1 springframework4.3.7.RELEASE 1.2 mybatis3.4.1 1.3 shiro1.3.2 1.4 servlet3.1.0 1.5 druid1.0.28 1.6 slf4j1.7.19 1.7 fastjson1.2.30 1.8 poi3.15 1.9 ...
  • 微信小程序带前后端

    2020-06-14 22:54:43
    填写以下信息: a.AppId:(暂无,不影响工具预览,无法手机微信预览,需要注册微信公众平台的应用号,才可具有(与开发者微信有关联,不是随便别人给一个就行))) b.项目名:随意 c.目录,选择解压后的sl目录(sl下有image,pages...
  • 在去年的时候,参加过学校的一个创业活动,在团队决定做一个关于图书的微信小程序以后,我负责做微信小程序的后台程序,因为初次接触,决定选用较为简单的PHP作为后台语言,实现了微信小程序的一些基本功能,例如对...
  • C#微信开发

    2017-12-24 10:35:37
    C#开发微信门户及应用教程   作者:伍华聪   C#开发微信门户及应用(1)--开始使用微信接口 6 1、微信账号 6 2、微信菜单定义 7 3、接入微信的链接处理 8 4、使用开发方式创建菜单 14 5、我创建的菜单案例 17 C#...
  • 基于wx-java的微信分享简介前期准备开始配置微信公众号测试号内网穿透后端代码前端代码 简介 最近做了个项目用到了微信分享功能,奈何认识的同学也没人会,只好自己研究文档博客来做了。看了不少博客,每篇博客都有...
  • 微信小程序支付绕坑指南 步骤 A:小程序向服务端发送商品详情、金额、openid B:服务端向微信统一下单 C:服务器收到返回信息二次签名发回给小程序 D:小程序发起支付 E:服务端收到回调 源代码已经上传到 ...
  • 一年的时间里,前前后后都在搞微信开发的相关模块,这不前一阵子,公司又开了个新项目,其中有一个就是类似于微信朋友圈的功能(我也不知道为啥要开发微信已有的功能啊,泪奔...),其中包含上传图片、录音、视频等...
  • .NET美容化妆企业微信小程序官网源码(独立后台+前端小程序) 美容化妆企业微信小程序官网,后台管理更新微信小程序上数据信息,测试无Bug,感兴趣的欢迎下载 1、后台内容管理:管理网站的pc和wap端的产品、文章、...
  • 微信小程序留言助手使用指南 前言 现在微信公众号留言功能不开通真的很麻烦,与读者之间缺少了很多的互动,所以小鹿就花费了一个月的时间,做了一款留言小程序,嵌入到公众号文章底部,点击进入用户即可进行留言,和...
  • 微信小程序学习 最近工作正好有闲暇时间,根据公司安排先前期学习...认识开发工具 目录结构与代码构成 JSON 配置文件 WXML 模版文件 WXSS 样式文件 JS 脚本文件 小程序的执行流程 小程序知识体系导图 小...
  • 网站后端设置好以后,下载wx开发者工具上传前端 注意在这里选择本地开发,不要选择云开发 不会的自行百度微擎小程序搭建教程 把前端文件里面的域名替换成自己的域名 最后上传到wx审核即可 注意:碰到啥不会的...
  • 接口免费,橙色风格新版短视频去水印源码,去水印微信小程序源码网站,去水印软件源码 程序截图 源码扫码测试 安装环境(需要材料):备案域名-服务器安装宝塔-安装Nginx或者Apache php5.6以上-安装sg11插件 小程序...
  • 如何使用微信开发者工具上传测试代码到腾讯云?可通过以下设置实现。 (1)登录小程序后台 进入https://mp.weixin.qq.com/使用注册小程序时的邮箱登录(勿使用公众号的邮箱登录),点击开发者工具如下,点击开通。...
1 2 3 4 5 ... 20
收藏数 2,241
精华内容 896