├── README.md
├── client
├── .wing
│ └── launch.json
├── app.js
├── app.json
├── app.wxss
├── jsconfig.json
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ └── logs
│ │ ├── logs.js
│ │ ├── logs.json
│ │ ├── logs.wxml
│ │ └── logs.wxss
└── utils
│ ├── qiniuUploader.js
│ └── util.js
└── server
└── qiniuTokenServer.js
/README.md:
--------------------------------------------------------------------------------
1 | # 微信小程序-七牛图片上传
2 |
3 | ### 说明:
4 |
5 | 实现了直接从客户端上传图片到七牛的功能,包含生成uptoken的服务端。
6 |
7 | ### 数据接口:
8 |
9 | - https://aime.getweapp.com/qiniu/uptoken
10 | - 自己uptoken服务端api
11 |
12 | ### 目录结构:
13 |
14 | - client — 客户端
15 | - server — 获取uptoken服务端
16 |
17 | ### 开发环境:
18 |
19 | 微信web开发者工具 v0.11.122100
20 |
21 | ### 项目截图:
22 |
23 | https://www.getweapp.com/project?projectId=5880baaa52e1e8733dc567de
24 |
25 | ### 感谢:
26 |
27 | 本项目原始版本由gpake提供:https://github.com/gpake/qiniu-wxapp-sdk
28 |
--------------------------------------------------------------------------------
/client/.wing/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "调试微信小程序",
6 | "type": "weapp",
7 | "request": "launch",
8 | "project": "${workspaceRoot}"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/client/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | //调用API从本地缓存中获取数据
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 | },
9 | getUserInfo:function(cb){
10 | var that = this;
11 | if(this.globalData.userInfo){
12 | typeof cb == "function" && cb(this.globalData.userInfo)
13 | }else{
14 | //调用登录接口
15 | wx.login({
16 | success: function () {
17 | wx.getUserInfo({
18 | success: function (res) {
19 | that.globalData.userInfo = res.userInfo;
20 | typeof cb == "function" && cb(that.globalData.userInfo)
21 | }
22 | })
23 | }
24 | });
25 | }
26 | },
27 | globalData:{
28 | userInfo:null
29 | }
30 | })
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/client/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "pages/index/index",
4 | "pages/logs/logs"
5 | ],
6 | "window":{
7 | "backgroundTextStyle":"light",
8 | "navigationBarBackgroundColor": "#238efa",
9 | "navigationBarTitleText": "七牛图片上传",
10 | "navigationBarTextStyle":"light"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/client/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .container {
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: center;
7 | justify-content: space-between;
8 | padding: 200rpx 0;
9 | box-sizing: border-box;
10 | }
11 |
--------------------------------------------------------------------------------
/client/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 |
4 | },
5 | "exclude": [
6 | ]
7 | }
--------------------------------------------------------------------------------
/client/pages/index/index.js:
--------------------------------------------------------------------------------
1 | const qiniuUploader = require("../../utils/qiniuUploader");
2 | //index.js
3 |
4 | // 初始化七牛相关参数
5 | function initQiniu() {
6 | var options = {
7 | region: 'ECN', // 华东区,生产环境应换成自己七牛帐户bucket的区域
8 | uptokenURL: 'https://aime.getweapp.com/qiniu/uptoken', // 生产环境该地址应换成自己七牛帐户的token地址,具体配置请见server端
9 | domain: 'https://oh39iobj6.qnssl.com/' // 生产环境该地址应换成自己七牛帐户对象存储的域名
10 | };
11 | qiniuUploader.init(options);
12 | }
13 |
14 | //获取应用实例
15 | var app = getApp()
16 | Page({
17 | data: {
18 | imageObject: {}
19 | },
20 | //事件处理函数
21 | onLoad: function () {
22 | console.log('onLoad')
23 | var that = this;
24 | },
25 | didPressChooesImage: function() {
26 | var that = this;
27 | didPressChooesImage(that);
28 | }
29 | });
30 |
31 | function didPressChooesImage(that) {
32 | initQiniu();
33 | // 微信 API 选文件
34 | wx.chooseImage({
35 | count: 1,
36 | success: function (res) {
37 | var filePath = res.tempFilePaths[0];
38 | // 交给七牛上传
39 | qiniuUploader.upload(filePath, (res) => {
40 | that.setData({
41 | 'imageObject': res
42 | });
43 | }, (error) => {
44 | console.error('error: ' + JSON.stringify(error));
45 | });
46 | }
47 | }
48 | // , {
49 | // region: 'ECN',
50 | // domain: 'balxqjka.btk.clouddn.com',
51 | // uptokenURL: 'myServer.cpm/api/uptoken'
52 | // }
53 | )
54 | }
55 |
--------------------------------------------------------------------------------
/client/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/client/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | hash: {{imageObject.hash}}\n\n
10 | key: {{imageObject.key}}\n\n
11 | imageURL: {{imageObject.imageURL}}
12 |
13 |
14 |
--------------------------------------------------------------------------------
/client/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 | /**index.wxss**/
2 |
3 | text {
4 | word-break: break-all;
5 | color:gray;
6 | line-height:1.3;
7 | }
8 |
9 | .main {
10 | height: 100%;
11 | display: flex;
12 | flex-direction: column;
13 | align-items: center;
14 | justify-content: space-between;
15 | padding: 100rpx 0;
16 | box-sizing: border-box;
17 |
18 | }
19 |
20 | .image-container {
21 | background-color: #f2f2f2
22 | }
23 |
24 | .data {
25 | padding:0 25px;
26 | text-align: left;
27 | display: block;
28 | font-size: 15px;
29 | word-break:break-all;
30 | }
31 |
32 | button {
33 | margin-bottom: 20px;
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/client/pages/logs/logs.js:
--------------------------------------------------------------------------------
1 | var util = require('../../utils/util.js')
2 | Page({
3 | data: {
4 | logs: []
5 | },
6 | onLoad: function () {
7 | this.setData({
8 | logs: (wx.getStorageSync('logs') || []).map(function (log) {
9 | return util.formatTime(new Date(log))
10 | })
11 | })
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/client/pages/logs/logs.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "查看启动日志"
3 | }
--------------------------------------------------------------------------------
/client/pages/logs/logs.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{index + 1}}. {{log}}
5 |
6 |
7 |
--------------------------------------------------------------------------------
/client/pages/logs/logs.wxss:
--------------------------------------------------------------------------------
1 | .log-list {
2 | display: flex;
3 | flex-direction: column;
4 | padding: 40rpx;
5 | }
6 | .log-item {
7 | margin: 10rpx;
8 | }
9 |
--------------------------------------------------------------------------------
/client/utils/qiniuUploader.js:
--------------------------------------------------------------------------------
1 | // created by gpake
2 | (function() {
3 |
4 | var config = {
5 | qiniuRegion: '',
6 | qiniuImageURLPrefix: '',
7 | qiniuUploadToken: '',
8 | qiniuUploadTokenURL: '',
9 | qiniuUploadTokenFunction: null
10 | }
11 |
12 | module.exports = {
13 | init: init,
14 | upload: upload,
15 | }
16 |
17 | // 在整个程序生命周期中,只需要 init 一次即可
18 | // 如果需要变更参数,再调用 init 即可
19 | function init(options) {
20 | config = {
21 | qiniuRegion: '',
22 | qiniuImageURLPrefix: '',
23 | qiniuUploadToken: '',
24 | qiniuUploadTokenURL: '',
25 | qiniuUploadTokenFunction: null
26 | };
27 | updateConfigWithOptions(options);
28 | }
29 |
30 | function updateConfigWithOptions(options) {
31 | if (options.region) {
32 | config.qiniuRegion = options.region;
33 | } else {
34 | console.error('qiniu uploader need your bucket region');
35 | }
36 | if (options.uptoken) {
37 | config.qiniuUploadToken = options.uptoken;
38 | } else if (options.uptokenURL) {
39 | config.qiniuUploadTokenURL = options.uptokenURL;
40 | } else if(options.uptokenFunc) {
41 | config.qiniuUploadTokenFunction = options.uptokenFunc;
42 | }
43 | if (options.domain) {
44 | config.qiniuImageURLPrefix = options.domain;
45 | }
46 | }
47 |
48 | function upload(filePath, success, fail, options) {
49 | if (null == filePath) {
50 | console.error('qiniu uploader need filePath to upload');
51 | return;
52 | }
53 | if (options) {
54 | init(options);
55 | }
56 | if (config.qiniuUploadToken) {
57 | doUpload(filePath, success, fail, options);
58 | } else if (config.qiniuUploadTokenURL) {
59 | getQiniuToken(function() {
60 | doUpload(filePath, success, fail, options);
61 | });
62 | } else if (config.qiniuUploadTokenFunction) {
63 | config.qiniuUploadToken = config.qiniuUploadTokenFunction();
64 | } else {
65 | console.error('qiniu uploader need one of [uptoken, uptokenURL, uptokenFunc]');
66 | return;
67 | }
68 | }
69 |
70 | function doUpload(filePath, success, fail, options) {
71 | var url = uploadURLFromRegionCode(config.qiniuRegion);
72 | var fileName = filePath.split('//')[1];
73 | if (options && options.key) {
74 | fileName = options.key;
75 | }
76 | var formData = {
77 | 'token': config.qiniuUploadToken,
78 | 'key': fileName
79 | };
80 | console.log('url:', url, 'filePath:', filePath, 'formData:', formData)
81 | wx.uploadFile({
82 | url: url,
83 | filePath: filePath,
84 | name: 'file',
85 | formData: formData,
86 | success: function (res) {
87 | var dataString = res.data
88 | var dataObject = JSON.parse(dataString);
89 | //do something
90 | var imageUrl = config.qiniuImageURLPrefix + dataObject.key;
91 | dataObject.imageURL = imageUrl;
92 | console.log(dataObject);
93 | if (success) {
94 | success(dataObject);
95 | }
96 | },
97 | fail: function (error) {
98 | console.log(error);
99 | if (fail) {
100 | fail(error);
101 | }
102 | }
103 | })
104 | }
105 |
106 | function getQiniuToken(callback) {
107 | wx.request({
108 | url: config.qiniuUploadTokenURL,
109 | success: function (res) {
110 | var token = res.data.uptoken;
111 | config.qiniuUploadToken = token;
112 | if (callback) {
113 | callback();
114 | }
115 | },
116 | fail: function (error) {
117 | console.log(error);
118 | }
119 | })
120 | }
121 |
122 | function uploadURLFromRegionCode(code) {
123 | var uploadURL = null;
124 | switch(code) {
125 | case 'ECN': uploadURL = 'https://up.qbox.me'; break;
126 | case 'NCN': uploadURL = 'https://up-z1.qbox.me'; break;
127 | case 'SCN': uploadURL = 'https://up-z2.qbox.me'; break;
128 | case 'NA': uploadURL = 'https://up-na0.qbox.me'; break;
129 | default: console.error('please make the region is with one of [ECN, SCN, NCN, NA]');
130 | }
131 | return uploadURL;
132 | }
133 |
134 | })();
--------------------------------------------------------------------------------
/client/utils/util.js:
--------------------------------------------------------------------------------
1 | function formatTime(date) {
2 | var year = date.getFullYear()
3 | var month = date.getMonth() + 1
4 | var day = date.getDate()
5 |
6 | var hour = date.getHours()
7 | var minute = date.getMinutes()
8 | var second = date.getSeconds();
9 |
10 |
11 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
12 | }
13 |
14 | function formatNumber(n) {
15 | n = n.toString()
16 | return n[1] ? n : '0' + n
17 | }
18 |
19 | module.exports = {
20 | formatTime: formatTime
21 | }
22 |
--------------------------------------------------------------------------------
/server/qiniuTokenServer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 作者:刘焱旺 yw@getweapp.com
3 | * 答疑交流QQ群:499859691
4 | */
5 |
6 | // api服务
7 | const Restify = require('restify')
8 | const Server = Restify.createServer()
9 | Server.use(Restify.queryParser())
10 | Server.use(Restify.bodyParser())
11 |
12 | // qiniu
13 | import qiniu from 'qiniu'
14 |
15 | // 监听端口号
16 | const PORT = 9885
17 |
18 | qiniu.conf.ACCESS_KEY = 'xxxx'; // 你的七牛帐户的ACCESS_KEY
19 | qiniu.conf.SECRET_KEY = 'xxxx'; // 你的七牛帐户的SECRET_KEY
20 |
21 | const bucket = 'xxxx'; // 你的七牛帐户的bucket
22 |
23 | /********** 业务处理开始 **********/
24 |
25 | // 获取uptoken
26 | Server.get('/uptoken', (req, res) => {
27 | const putPolicy = new qiniu.rs.PutPolicy(bucket)
28 | const uptoken = putPolicy.token()
29 | console.log('get token:', uptoken)
30 | res.send({
31 | code: 0,
32 | uptoken: uptoken
33 | })
34 | })
35 |
36 | /********** 业务处理结束 **********/
37 |
38 | // 监听端口开启api服务
39 | Server.listen(PORT, () => {
40 | console.log('开启服务器,端口号:', PORT)
41 | })
42 |
--------------------------------------------------------------------------------