【教程】微信小程序如何拍摄图片及视频并上传到后台进行存储

需求分析

微信小程序 中需要使用手机拍摄照片以及视频上传到后台进行进一步的操作,需要解决以下两个问题:

  1. 微信小程序如何拍摄照片及视频
  2. 如何将拍摄的照片及视频上传到后台进行存储

解决方案

前端开发:微信小程序原生

后端开发:Flask

如何拍摄照片及视频

微信小程序如何拍摄照片及视频:使用wx.chooseMediaAPI来实现

该API用于拍摄或从手机相册中选择图片或视频,文档链接为:developers.weixin.qq.com/miniprogram...

简单示例:

javascript 复制代码
function test()
{
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'],
camera: 'back',
success(res) {
console.log(res)
},
fail(res){
console.log(res)
}
})
}

主要参数含义如下:

  • count:最多可以选择的文件个数
  • mediaType:文件类型,可选值为:['image']/['video']/['image','video'],默认值为['image','video'],意为即允许拍摄图片也允许拍摄视频
  • sourceType:文件来源,可选值为['album']/[ 'camera']/['album', 'camera'],默认值为['album', 'camera'],意为即允许从相册选择,也允许直接拍摄
  • camera:仅在 sourceType 为 camera 时生效,使用前置或后置摄像头,可选值为'back'/'front',默认值为'back'

回调参数res:

  • tempFiles:本地临时文件列表,其中的tempFilePath是本地临时文件路径,也是该示例中的核心参数;
  • type:文件类型

更多参数以及回调参数请参考官方文档

由上可知,我们首选需要调用wx.chooseMedia函数,选择拍摄照片或者视频,然后在回调函数中拿到本地临时文件路径,这样就获取到了拍摄的照片或视频,但我们拿到的并不是一个完整的.png/.mp4文件,而是一个临时文件链接,例如:http://tmp/z7bXVKwgyWTKcbc89c663afd501de1d27ed321f8591c.jpg

这样的文件链接可以在开发者工具中打开:

但该链接无法在外部进行访问,因此就涉及到如何将该链接所代表的文件上传到后台的问题;

这样的文件在小程序中被称为"本地临时文件",仅在当前生命周期内保证有效,重启之后不一定可用

更多内容请参考官方文档:developers.weixin.qq.com/miniprogram...

如何上传后台进行存储

如何将拍摄的照片及视频上传到后台进行存储:

  • 前端:使用wx.uploadFileAPI
  • 后端:使用request.files['photo'].stream.read()来读取文件

前端代码

有关wx.uploadFile可以参考:developers.weixin.qq.com/miniprogram...

主要参数有:

  • url:开发者服务器地址,即要访问的接口
  • filePath:要上传的文件路径(本地路径),这里即是通过wx.chooseMedia回调中的tempFilePath
  • formData:HTTP 请求中其他额外的 form data,允许我们传输文件的时候携带一些其他的参数,比如说文件名称;

因此完整的前端代码如下(上传图片):

javascript 复制代码
//拍摄照片
photoCapture() {
let that = this
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'],
camera: 'back',
success(res) {
that.setData({
photoLink: res.tempFiles[0].tempFilePath,
})
console.log(res.tempFiles[0].tempFilePath)
console.log('图片拍摄成功')
wx.showLoading({
title: '正在上传图片',
mask: true
})

//图片上传
wx.uploadFile({
url: 'http://localhost:5000/uploadImage',
filePath: res.tempFiles[0].tempFilePath,
name: 'photo',
formData: {
fileName: 'photoTest.png'
},
success(res) {
wx.showToast({
title: '图片上传成功',
})
}
})
},
fail(res) {
console.log('图片拍摄失败')
}
})
}

首先拍摄照片,然后上传文件

后端代码

后端使用flask进行开发

通过request.files来接收文件

通过request.form来接收wx.uploadFileformData中携带的数据

通过write方法将接收到的文件保存到本地

因此完整的后端代码如下(上传图片):

sql 复制代码
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World'

# 图片上传
@app.route('/uploadImage', methods=["POST"])
def uploadImage():
video = request.files['photo'].stream.read()
name = request.form['fileName']
if not files_exists(name, 2):
file_path = os.getcwd() + '\images\' + name
with open(file_path, 'ab') as f:
f.write(video)
return 'image upload success'
else:
return 'image already exist'

# 判断文件是否已经存在
def files_exists(file_name, choice):
if choice == 1:
path = os.getcwd() + '\videos\'
video_path = os.path.join(path, file_name)
return os.path.isfile(video_path)
else:
path = os.getcwd() + '\images\'
image_path = os.path.join(path, file_name)
return os.path.isfile(image_path)

if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)

运行结果

首先启动后端服务,然后小程序初始页面如下:

点击按钮拍摄图片,可以看到图片成功预览在小程序中:

在NetWork中可以看到接口的返回值:

图片上传成功;在后端也能看到图片已经保存下来了:

所有代码

前端代码

index.wxml:

bash 复制代码
<button type="primary" bind:tap="photoCapture">点击拍摄图片</button>
<image src="{{photoLink}}"></image>
<button type="primary" bind:tap="videoCapture">点击拍摄视频</button>
<image src="{{videoLink}}"></image>

index.wxss:

css 复制代码
page {
padding-top: 100rpx;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
image{
margin-top: 50rpx;
margin-bottom: 50rpx;
width: 600rpx;
height: 400rpx;
border: 1px solid black;
}

index.js:

vbnet 复制代码
Page({
data: {
photoLink: '',
videoLink: '',
},

//拍摄照片
photoCapture() {
let that = this
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sourceType: ['camera'],
camera: 'back',
success(res) {
that.setData({
photoLink: res.tempFiles[0].tempFilePath,
})
console.log(res.tempFiles[0].tempFilePath)
console.log('图片拍摄成功')
wx.showLoading({
title: '正在上传图片',
mask: true
})

//图片上传
wx.uploadFile({
url:'http://localhost:5000/uploadImage',
filePath: res.tempFiles[0].tempFilePath,
name: 'photo',
formData: {
fileName:'photoTest.png'
},
success(res) {
wx.showToast({
title: res.data,
})
}
})
},
fail(res) {
console.log('图片拍摄失败')
}
})
},

//拍摄视频
videoCapture() {
let that = this
wx.chooseMedia({
count: 1,
mediaType: ['video'],
sourceType: ['camera'],
maxDuration: 60,
camera: 'back',
success(res) {
that.setData({
videoLink: res.tempFiles[0].thumbTempFilePath
})
console.log('视频拍摄成功')
console.log(res.tempFiles[0].tempFilePath)
wx.showLoading({
title: '正在上传视频',
mask: true
})

//视频上传
wx.uploadFile({
url:'http://localhost:5000/uploadVideo',
filePath: res.tempFiles[0].tempFilePath,
name: 'video',
formData: {
fileName:'videoTest.mp4'
},
success(res) {
wx.showToast({
title: res.data,
})
}
})
},
fail(res) {
console.log('图片拍摄失败')
}
})
}
})

后端代码

sql 复制代码
from flask import Flask, request
import os

app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World'

@app.route('/uploadVideo', methods=["POST"])
def uploadVideo():
video = request.files['video'].stream.read()
name = request.form['fileName']
if not files_exists(name, 1):
file_path = os.getcwd() + '\videos\' + name
with open(file_path, 'ab') as f:
f.write(video)
return 'upload success'
else:
return 'already exist'


@app.route('/uploadImage', methods=["POST"])
def uploadImage():
video = request.files['photo'].stream.read()
name = request.form['fileName']
if not files_exists(name, 2):
file_path = os.getcwd() + '\images\' + name
with open(file_path, 'ab') as f:
f.write(video)
return 'upload success'
else:
return 'already exist'


def files_exists(file_name, choice):
if choice == 1:
path = os.getcwd() + '\videos\'
video_path = os.path.join(path, file_name)
return os.path.isfile(video_path)
else:
path = os.getcwd() + '\images\'
image_path = os.path.join(path, file_name)
return os.path.isfile(image_path)


if __name__ == '__main__':
app.run(host='127.0.0.1', port=5000)
相关推荐
是一碗螺丝粉几秒前
React Native 运行时深度解析
前端·react native·react.js
Jing_Rainbow2 分钟前
【前端三剑客-9 /Lesson17(2025-11-01)】CSS 盒子模型详解:从标准盒模型到怪异(IE)盒模型📦
前端·css·前端框架
爱泡脚的鸡腿5 分钟前
uni-app D6 实战(小兔鲜)
前端·vue.js
青年优品前端团队7 分钟前
🚀 不仅是工具库,更是国内前端开发的“瑞士军刀” —— @qnvip/core
前端
北极糊的狐15 分钟前
Vue3 中父子组件传参是组件通信的核心场景,需遵循「父传子靠 Props,子传父靠自定义事件」的原则,以下是资料总结
前端·javascript·vue.js
codetown22 分钟前
openai-go通过SOCKS5代理调用外网大模型
人工智能·后端
星辞树23 分钟前
MIT 6.824 Lab 3 通关实录:从 Raft 到高可用 KV 存储
后端
看到我请叫我铁锤1 小时前
vue3中THINGJS初始化步骤
前端·javascript·vue.js·3d
q***25211 小时前
SpringMVC 请求参数接收
前端·javascript·算法
q***33371 小时前
Spring Boot项目接收前端参数的11种方式
前端·spring boot·后端