安卓上传图片视频录像拍照

更新时间: 2025-09-19 10:20:21

最近公司有个APP开发的任务交给我了,这个APP有个上传图片或视频的功能,也可以现场拍摄,先看一下效果吧:

不过公司还有个需求是上传的图片或者视频没有提交也需要在本地有缓存,退出APP下次再打开的时候要能看,经过多番测试之后,我发现

  • 图片和现场拍摄的图片返回的临时地址可以通过uni.saveFile缓存
  • 选择的相册里的视频返回的是一串链接到视频播放的地址,这个地址跟视频存储的地址一一对应不会变,可以直接缓存
  • 现场拍摄的视频不能缓存,也许可以,但我实在没解决
    因此,我给前端的UI做了一下调整:

# 实现

# 直接选择或拍摄

// 用于存储选中的媒体文件信息  
const list = []

// 选择图片/视频
function chooseMedia() {
  uni.chooseMedia({
	mediaType: ['image', 'video'], // 支持图片和视频
	sourceType: ['album', 'camera'], // 支持相册和相机
	maxDuration: 60, // 视频最大时长(秒)
	sizeType: ['compressed'], // 压缩文件
	success: (res) => {
	  console.log('选择媒体成功', res);
	  
	  for(let i = 0;i < res.tempFiles.length; i++) {
		  if (res.tempFiles[i].size > 100 * 1024 * 1024) {
			uni.showToast({
			  title: '图片或视频大小不能超过100MB',
			  icon: 'none'
			});
			continue
		  }
		  // 添加到媒体列表
		  list.push(res.tempFiles[i])
	  }
	},
	fail: (err) => {
	  console.error('选择媒体失败', err);
	  uni.showToast({ title: '选择文件失败', icon: 'none' });
	}
  });
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

这段代码实现了一个图片/视频选择功能,允许用户从手机相册或相机拍摄中选择媒体文件,并对文件大小进行限制(最大100MB)。主要用于社交、内容上传类App的媒体选择场景。

# 选择是从相册选择还是拍摄照片

// 储存选中的媒体文件信息  
const fileList = []

async function handleUpload() {
	
  // 1. 让用户选择来源
  const actionResult = await new Promise((resolve) => {
    uni.showActionSheet({
      itemList: ['从相册选择', '拍摄照片'],  // 操作菜单选项
      success: resolve,  // 用户选择后执行resolve  
      fail: () => resolve({ tapIndex: -1 })  // 取消时返回tapIndex: -1
    });
  });

  if (actionResult.tapIndex === -1) return;  // 用户取消,终止流程  
 
  // 2. 根据选择调用不同配置的 chooseMedia
  if (actionResult.tapIndex === 0) {
    // 相册选择:允许图片和视频
    chooseFromAlbum();
  } else {
    // 相机拍摄:仅允许图片
    takePhoto();
  }
}

// 从相册选择(支持图片和视频)
function chooseFromAlbum() {
    uni.chooseMedia({
      count: 1,
      mediaType: ['image', 'video'], // 同时支持图片和视频
      sourceType: ['album'], // 仅相册
      maxDuration: 30, // 视频最大时长(秒)
	  success: (res) => {
	  		  handleMediaResult(res.tempFiles[0]);
	  },
	  fail:(e) => {
	  		  uni.showToast({ title: '拍摄失败', icon: 'none' });
	  }
    });
}

// 拍摄照片(禁止视频)
function takePhoto() {
    uni.chooseMedia({
      count: 1,
      mediaType: ['image'], // 仅图片
      sourceType: ['camera'], // 仅相机
      camera: 'back', // 默认后置摄像头
	  success: (res) => {
		  handleMediaResult(res.tempFiles[0]);
	  },
	  fail:(e) => {
		  uni.showToast({ title: '拍摄失败', icon: 'none' });
	  }
    });
}

// 统一处理选择结果
function handleMediaResult(file) {
	if (file.size > 100 * 1024 * 1024) {
		uni.showToast({
		  title: '图片或视频大小不能超过100MB',
		  icon: 'none'
		});
		return
	}
	fileList.push(file);  // 符合要求,添加到文件列表  
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

这段代码实现了一个更完善的媒体选择功能,允许用户从手机相册选择或直接拍摄照片/视频,并限制文件大小不超过100MB。相比基础版本,新增了来源选择功能。

我们来梳理一下逻辑:

  • 当用户点击上传按钮调用handleUpload函数
    • 选择从相册选择,调用chooseFromAlbum函数
    • 选择拍摄照片,调用takePhoto函数 然后选完了照片或视频以后检查图片或视频大小再处理

关键技术点:

  • async/await异步语法
    async声明函数为异步函数,await等待Promise完成。解决了传统回调函数嵌套("回调地狱")问题,让代码更易读。

  • Promise包装异步API:
    uni.showActionSheet是异步API(需要等待用户选择),用new Promise包装后可配合await使用,实现"同步写法执行异步操作"。