详解微信小程序 wx.uploadFile 的编码坑


Posted in Javascript onJanuary 23, 2017

编写微信小程序时,用到 wx.uploadFile,用来上传图片+文本信息.然而在编写过程中,由于官方的 demo 和文档描述很少,在几个坑上耗费了不少时间.

这里分享一个和编码有关的坑,主要是由于真机预览时 formData 中的非字母、数字的 ASCII 编码的字符如中文、泰文传输到服务端将不会自动进行转码码,并会会产生乱码及溢出,从而导致错误。

微信的 uploadFile 类似与 html 中的form带文件上传的表单 ( enctype=”multipart/form-data” ), 这样 post 上传的表单,可以包含文件,同时包含其它的键值数据。微信小程序用 uploadFile 实现类似的操作. 我的微信小程序端的uploadFile 代码如下 :

wx.uploadFile({
      url: 'https://<upload_domain>/save',
      filePath:photoPath, //待上传的图片,由 chooseImage获得
      name:'food_image',
      formData: {
       latitude:0.0,
       longitude:0.0,
       restaurant_id:0,
       city:'北京',
       name:'beijing' // 名称
      }, // HTTP 请求中其他额外的 form data
      success: function(res){
       console.log("addfood success",res);
      },
      fail: function(res) {
       console.log("addfood fail",res);
      },
     })
},

服务端我用的 php 编写,这里接受文件的接口为 save ,我将 POST和_FILES 里的数据直接输出到info.log 文件中用来进行调试.代码如下:

public function save(Request $request)
{
  error_log("FILES:" . json_encode($_FILES) . "\r\n", 3, "./logs/info.log");
  error_log("POST: " . json_encode($_POST) . "\r\n", 3, "./logs/info.log");
  error_log("city: " . $_POST["city"] . "\r\n", 3, "./logs/info.log");
  error_log("name: " . $_POST["name"] . "\r\n", 3, "./logs/info.log");
  error_log("latitude: " . $_POST["latitude"] . "\r\n", 3, "./logs/info.log");
  error_log("longitude: " . $_POST["longitude"] . "\r\n", 3, "./logs/info.log");
  error_log("restaurant_id: " . $_POST["restaurant_id"] . "\r\n", 3, "./logs/info.log");
  error_log("tags: " . $_POST["city"] . "\r\n", 3, "./logs/info.log");
echo 'success';
}

在小程序开发工具中运行小程序,选择好图片后进行上传操作,服务器端成功接收到数据,info.log输出的数据信息如下:

FILES:{"food_image":{"name":"store_265332457o6zAJszC4WsrwhUy55eh7iKJt7EQ1480318543139.jpg","type":"image\/jpeg","tmp_name":"\/tmp\/phpe3zGok","error":0,"size":845941}}
POST: {"latitude":"0","longitude":"0","restaurant_id":"0","tags":"","city":"\u5317\u4eac","name":"\u0e1b\u0e31\u0e01\u0e01\u0e34\u0e48\u0e07"}
city: 北京
name: ปักกิ่ง
latitude: 0
longitude: 0
restaurant_id: 0

( ps:php 中,FILES 里有 tmp_name 为收到了文件,将临时文件从该路径中移动到指定目录便可保存文件,这里看到有 /tmp/phpe3zGok 临时文件,说明成功收到了文件) 将小程序预览到手机上,点击上传,但却出现了问题,如下所示:

详解微信小程序 wx.uploadFile 的编码坑

POST 数据为空, FILES 成功收到,而单独输出的$_POST数据出现乱码(中文和泰文部分),出现了溢出.

可以看到,非英文,数字的数据是乱码,而其它数据没有问题,显然是编码出现了问题,POST 数据输出为空,由于乱码导致了溢出使得格式错乱.

编码有问题,那么就尝试改变它的编码进行传输, uploadFile 的参数中加入

header{“chartset”:”utf-8”}
//或者 
header{"content-type":'application/x-www-form-urlencoded'}

但是都没有什么效果,依然是在微信小程序工具中有效,而手机真机预览的时候出现乱码.在看到这篇帖子 【新手跳坑指南《三十九》wx.uploadFile】 才知道header 里的数据在真机预览的时候是无效的,需要改到 formData 中,受到了启发,尝试将编码数据加入formData 中,但仅仅传输了数据,并没有改变编码.依然是小程序开发工具中调试成功,而真机预览出了问题,这个估计要微信团队来回答了。

知道 header 是个bug , 那么编码的操作暂时只能手动进行了,于是我将小程序段的数据都进行编码. 在 javascript 中,字符串编码函数是 encodeURI, 在小程序中尝试,也有该函数,所以我将小程序代码改为如下

wx.uploadFile({
      url: 'https://<upload_domain>/save',
      filePath:photoPath, //待上传的图片,由 chooseImage获得
      name:'food_image',
      formData: {
       latitude:encodeURI(0.0),
       longitude:encodeURI(0.0),
       restaurant_id:encodeURI(0),
       city:encodeURI('北京'),
       name:encodeURI('beijing') // 名称
      }, // HTTP 请求中其他额外的 form data
      success: function(res){
       console.log("addfood success",res);
      },
      fail: function(res) {
       console.log("addfood fail",res);
      },
     })
},

服务器端, php 进行 url 解码的函数是 urldecode

public function save(Request $request)
{
  error_log("FILES:" . json_encode($_FILES) . "\r\n", 3, "./logs/info.log");
  error_log("POST: " . json_encode($_POST) . "\r\n", 3, "./logs/info.log");
  error_log("city: " . urldecode($_POST["city"]) . "\r\n", 3, "./logs/info.log");
  error_log("name: " . urldecode($_POST["name"]) . "\r\n", 3, "./logs/info.log");
  error_log("latitude: " . urldecode($_POST["latitude"]) . "\r\n", 3, "./logs/info.log");
  error_log("longitude: " . urldecode($_POST["longitude"]) . "\r\n", 3, "./logs/info.log");
  error_log("restaurant_id: " . urldecode($_POST["restaurant_id"]) . "\r\n", 3, "./logs/info.log");
  error_log("tags: " . urldecode($_POST["city"]) . "\r\n", 3, "./logs/info.log");
  echo 'success';
}

再次测试,真机预览测试输出如下:

ILES:{"food_image":{"name":"jpeg","type":"image\/jpeg","tmp_name":"\/tmp\/php1svqDs","error":0,"size":9561}}
POST: {"restaurant_id":"0","tags":"","longitude":"0","latitude":"0","city":"%E5%8C%97%E4%BA%AC","name":"%E0%B8%9B%E0%B8%B1%E0%B8%81%E0%B8%81%E0%B8%B4%E0%B9%88%E0%B8%87"}
city: 北京
name: ปักกิ่ง
latitude: 0
longitude: 0
restaurant_id: 0

可以看到,所有数据都正常输出,其中POST 数据中 city 和 name未解码前是 urlencode 编码形式的数据,解码后正常输出.
至此,我想使用小程序上传带文件信息到服务器端算是调通了, 希望这个方法能对出现同样问题的同学有一定帮助。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery 翻牌或百叶窗效果(内容三秒自动切换)
Jun 14 Javascript
jQuery解决下拉框select设宽度时IE 6/7/8下option超出显示不全
May 27 Javascript
利用javaScript实现点击输入框弹出窗体选择信息
Dec 11 Javascript
js中的caller和callee属性介绍和例子
Jun 07 Javascript
jquery通过扩展select控件实现支持enter或focus选择的方法
Nov 19 Javascript
初识angular框架后的所思所想
Feb 19 Javascript
JQuery Ajax WebService传递参数的简单实例
Nov 02 Javascript
Node.js 实现简单的接口服务器的实例代码
May 23 Javascript
JavaScript实现多叉树的递归遍历和非递归遍历算法操作示例
Feb 08 Javascript
Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件
Jun 19 Javascript
vue项目中引入Sass实例方法
Aug 27 Javascript
vue下载二进制流图片操作
Oct 26 Javascript
微信小程序侧边栏滑动特效(左右滑动)
Jan 23 #Javascript
微信小程序技巧之show内容展示,上传文件编码问题
Jan 23 #Javascript
Javascript同时声明一连串(多个)变量的方法
Jan 23 #Javascript
jQuery点击导航栏选中更换样式的实现代码
Jan 23 #Javascript
jQuery弹出层插件popShow(改进版)用法示例
Jan 23 #Javascript
JS判断指定dom元素是否在屏幕内的方法实例
Jan 23 #Javascript
jQuery弹出层插件popShow用法示例
Jan 23 #Javascript
You might like
深入解析php之sphinx
2013/05/15 PHP
php实现把url转换迅雷thunder资源下载地址的方法
2014/11/07 PHP
smarty中常用方法实例总结
2015/08/07 PHP
浅谈php中urlencode与rawurlencode的区别
2016/09/05 PHP
PHP多进程简单实例小结
2019/11/09 PHP
PHP 进程池与轮询调度算法实现多任务的示例代码
2019/11/26 PHP
jQuery 获取对象 根据属性、内容匹配, 还有表单元素匹配
2010/05/31 Javascript
一个报数游戏js版(约瑟夫环问题)
2010/08/05 Javascript
将HTMLCollection/NodeList/伪数组转换成数组的实现方法
2011/06/20 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
2013/02/05 Javascript
AngularJS入门教程(一):静态模板
2014/12/06 Javascript
jQuery中常用的遍历函数用法实例总结
2015/09/01 Javascript
js实现模拟银行卡账号输入显示效果
2015/11/18 Javascript
javascript另类方法实现htmlencode()与htmldecode()函数实例分析
2016/11/17 Javascript
5分钟打造简易高效的webpack常用配置
2017/07/04 Javascript
ReactNative踩坑之配置调试端口的解决方法
2017/07/28 Javascript
vue获取input输入值的问题解决办法
2017/10/17 Javascript
详解vue-cli+element-ui树形表格(多级表格折腾小计)
2019/04/17 Javascript
如何使用原生Js实现随机点名详解
2021/01/06 Javascript
[56:00]2018DOTA2亚洲邀请赛 4.6 淘汰赛 VP vs TNC 第二场
2018/04/10 DOTA
python计算方程式根的方法
2015/05/07 Python
python实现马耳可夫链算法实例分析
2015/05/20 Python
Python 提取dict转换为xml/json/table并输出的实现代码
2016/08/28 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
在pandas中一次性删除dataframe的多个列方法
2018/04/10 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
python matplotlib画图库学习绘制常用的图
2019/03/19 Python
在ipython notebook中使用argparse方式
2020/04/20 Python
python处理写入数据代码讲解
2020/10/22 Python
Traffic People官网:女式花裙、上衣和连身裤
2020/10/12 全球购物
六十岁生日答谢词
2014/01/10 职场文书
监察建议书格式
2014/05/19 职场文书
考研英语复习计划
2015/01/19 职场文书
行政答辩状范文
2015/05/21 职场文书
2016年党员岗位承诺书
2016/03/24 职场文书
灵能百分百第三季什么时候来?
2022/03/15 日漫