[server]基于uniapp创建小程序并上传照片到阿里云OSS

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ysgjiangsu/article/details/88665894

先说在前头,最近忙,随想随记,所以有些博客写了一半就发了,后续会慢慢补齐的。抱歉!

前端使用uniapp开发,后台挂在阿里云。选uniapp开发的原因是我这边人手不够,同时也不想维护这么多客户端,故选之。
新建一个uniapp工程,选择hello demo,找到pages/API/upload-file.vue文件

<template>
	<view>
		<page-head :title="title"></page-head>
		<view class="uni-padding-wrap uni-common-mt">
			<view class="demo">
				<block v-if="imageSrc">
					<image :src="imageSrc" class="image" mode="widthFix"></image>
				</block>
				<block v-else>
					<view class="uni-hello-addfile" @click="chooseImage">+ 选择图片</view>
				</block>
			</view>
		</view>
	</view>
</template>
<script>
	export default {
		data() {
			return {
				title: 'uploadFile',
				imageSrc: ''
			}
		},
		onUnload() {
			this.imageSrc = '';
		},
		methods: {
			chooseImage: function() {
				uni.chooseImage({
					count: 1,
					sizeType: ['compressed'],
					sourceType: ['album'],
					success: (res) => {
						console.log('chooseImage success, temp path is', res.tempFilePaths[0])
						var imageSrc = res.tempFilePaths[0]
						uni.uploadFile({
							url: 'http://yourbucketname.oss-cn-shanghai.aliyuncs.com',
							filePath: imageSrc,
							fileType: 'image',
							name: 'file',
							formData:{
								name: res.tempFilePaths[0],
								'key' : "${filename}",
								'policy': 'yourpolicycaculated',
								'OSSAccessKeyId': 'yourosskeyid', 
								'success_action_status' : '200', 
								//让服务端返回200,不然,默认会返回204
								'signature': 'yoursignaturecaculated',
							},
							success: (res) => {
								console.log('uploadImage success, res is:', res)
								uni.showToast({
									title: '上传成功',
									icon: 'success',
									duration: 1000
								})
								this.imageSrc = imageSrc
							},
							fail: (err) => {
								console.log('uploadImage fail', err);
								uni.showModal({
									content: err.errMsg,
									showCancel: false
								});
							}
						});
					},
					fail: (err) => {
						console.log('chooseImage fail', err)
					}
				})
			}
		}
	}
</script>

<style>
	.image {
		width: 100%;
	}

	.demo {
		background: #FFF;
		padding: 50upx;
	}
</style>

问题来了,这些需要计算的formdata怎么来的,最简单的就是
阿里云官方案例
在这里插入图片描述
在阿里的upload.js文件中,加个函数,如下:

function consoleinfo()
{
    console.log('policy:'+this.policyBase64)
    console.log('keyid:'+this.accessid)
    console.log('signature:'+this.signature)
}

阿里的例子会给出计算的结果,你直接对应填进去就可以了。然而,在OSS端得到的是奇怪的文件名,
在这里插入图片描述
问题来自微信:
在这里插入图片描述
在上图可以看到,temp path已经被微信小程序改了,所以啊我们OSS获得的就是被改掉的名字了。一般地,我们自己应该对上传到OSS的文件进行命名。如果一定要真实的名字,我找找解决办法再补上来

第二个问题:签名密钥放前端肯定是不行的,那如何放在后台呢,pages/API/upload-file.vue文件修改后如下:

<template>
	<view>
		<page-head :title="title"></page-head>
		<view class="uni-padding-wrap uni-common-mt">
			<view class="demo">
				<block v-if="imageSrc">
					<image :src="imageSrc" class="image" mode="widthFix"></image>
				</block>
				<block v-else>
					<view class="uni-hello-addfile" @click="chooseImage">+ 选择图片</view>
				</block>
			</view>
		</view>
	</view>
</template>
<script>
	const requestUrl = 'http://xxx.xx.xxx.xxx:xxxx'//用你自己的server + port
	export default {
		data() {
			return {
				title: 'uploadFile',
				imageSrc: ''
			}
		},
		onUnload() {
			this.imageSrc = '';
		},
		methods: {
			sendRequest: async function() {
				let that = this
				return await new Promise((resolve,reject)=>{
					uni.request({
						url: requestUrl,
						dataType: 'text',
						data: {
							noncestr: Date.now()
						},
						success: (res) => {
							console.log('request success', res)
							uni.showToast({
								title: '请求成功',
								icon: 'success',
								mask: true,
								duration: 2000
							});
							resolve(JSON.parse(res.data))
						},
						fail: (err) => {
							console.log('request fail', err);
							uni.showModal({
								content: err.errMsg,
								showCancel: false
							});
						},
						complete: () => {
							this.loading = false;
						}
					});
				})
			},
			chooseImage: function() {
				let that = this
				uni.chooseImage({
					count: 1,
					sizeType: ['compressed'],
					sourceType: ['album'],
					success: (res) => {
						console.log('chooseImage success, temp path is', res.tempFilePaths[0])
						var imageSrc = res.tempFilePaths[0]
						that.sendRequest().then((resdata)=>{
							console.log('wearehere')
							console.log(that === this)
							uni.uploadFile({
								url: resdata.host,
								filePath: imageSrc,
								fileType: 'image',
								name: 'file',
								formData:{
									name: res.tempFilePaths[0],
									key : "root/20190319.jpg",//我放在root下,你视情况而定
									policy: resdata.policy,
									OSSAccessKeyId: resdata.accessid, 
									success_action_status : '200', 
									//让服务端返回200,不然,默认会返回204
									signature: resdata.signature,
								},
								success: (res) => {
									console.log('uploadImage success, res is:', res)
									uni.showToast({
										title: '上传成功',
										icon: 'success',
										duration: 1000
									})
									console.log(that === this)
									this.imageSrc = imageSrc
								},
								fail: (err) => {
									console.log('uploadImage fail', err);
									uni.showModal({
										content: err.errMsg,
										showCancel: false
									});
								}
							});						
						});

					},
					fail: (err) => {
						console.log('chooseImage fail', err)
					}
				})
			}
		}
	}
</script>

<style>
	.image {
		width: 100%;
	}

	.demo {
		background: #FFF;
		padding: 50upx;
	}
</style>

老生常谈的几个问题

  1. this指向:
    我在好几处都console了that === this,真心被搞得懵逼,微信的代码风格是:进函数就先来个
    let that = this,这确实是个规避this作用域的好办法。然而,uniapp有时候在内部还在用this,这个this到底指向哪里,所以我加了判断输出
    结论:this指向当前的执行对象或者说执行环境。执行对象不变,指向也不变。在chooseimage后,函数层层调用,执行对象一直没变,因此this指向不变。具体this辨析,可参考阮一峰大神的博客

  2. var let const对比:
    假定你有C/C++基础哈,在C/C++中,你用{}扩起一段原本已经是个整体的代码是多此一举的,比如:

a = 0;
{
	a ++;
}
a++;

这个大括号去掉也不影响,但是在js中,{}表示块,也就引入了块作用域的概念。

var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。这个跟C/C++中的局部变量一回事

let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。let类似于var,只不过是用在块里的局部变量

const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。简言之,const是一个具有初值且不能被修改的let

关于三者对比,可参考阮一峰大神博客

  1. 异步实现:
    之前代码的思路是,直接request 我的server,拿到签名报上去。然而,这是不行的。因为,request是异步的,不是立马就能拿到返回结果的。而后续的upload参数依赖request的返回值,所以必须在request完成后才能搞upload的事情。因此,我加入了promise.then结构。

下面再说服务器配置:
A. 请参考阿里云官方案例Go
B. 请按要求改写服务器地址以及端口
C. 启动服务器端口侦听,注意注意注意:
执行这条语句开启侦听1234端口,go run appserver.go 0.0.0.0 1234

作为一个小白,我按阿里云的案例多次尝试都不行,找了一些资料,有人说是0 0 0 0就OK。虽然没问题了,但是没找到原因。路过的朋友知道的帮个忙解释一下啊,多谢多谢

猜你喜欢

转载自blog.csdn.net/ysgjiangsu/article/details/88665894