async function uploadToQiniu(filePaths) {
return new Promise((resolve, reject) => {
const files = filePaths.map((path, idx) => ({
name: 'file',
uri: path
}));
uni.uploadFile({
url: `${env.API_BASE_URL}/api/v1/records/upload_img`,
files: files,
formData: {
key: +new Date()
},
success: (res) => {
try {
const { code, data } = JSON.parse(res.data);
if (code === 0) resolve(data);
else reject(new Error('上传失败'));
} catch (e) {
reject(e);
}
},
fail: reject
});
});
}
对于这个问题,其实官网已经将踩坑点说明了
关键问题就是name参数的值是一样的,如果不一样,后端使用多个@RequestParam接收,是可以接收到的,如:
@RequestParam("file_01")
@RequestParam("file_02")
@RequestParam("file_03")
……
但这样太麻烦了,使用 MultipartRequest 可以解决这个问题,app端代码不变,服务端代码稍作修改,如下:
@PostMapping("/upload_img")
public R<List<String>> upload(
// 按照常理来说,会注入所有标识为file的文件,但是使用uni.uploadFile出bug了 // @RequestParam("file") MultipartFile[] files,
MultipartRequest req,
@RequestParam(value = "key", required = false ) String keyPrefix) {
// 通过这样处理,收集name字段标识的文件,如果name不同,可以分开收集,相同就收集一个列表
List<MultipartFile> files = new ArrayList<>();
req.getMultiFileMap()
.forEach((fieldName, multipartFiles) -> {
files.addAll(multipartFiles);
});
//后续逻辑
List<String> urls = IntStream.range(0, files.size())
.mapToObj(i -> {
MultipartFile file = files.get(i);
// 生成唯一 key:前缀 + 序号 + 原扩展名
String ext = FilenameUtils.getExtension(file.getOriginalFilename());
String realKey = keyPrefix == null ? null
: String.format("%s_%d.%s", keyPrefix, i, ext);
try {
return qiNiuTemplate.upload(realKey, file.getInputStream(), file.getSize());
} catch (IOException e) {
log.error("上传失败: {}", file.getOriginalFilename(), e);
return "ERROR:" + file.getOriginalFilename();
}
})
.collect(Collectors.toList());
return R.ok(urls);
}
简单总结一下:在app端使用uni.uploadFile一次性上传多个文件,服务端自动注入失效了(只能注入第一个),改动服务端接口形式,才能正常使用。
补充:如果name字段相同时,使用 MultipartRequest 还是只能收到一个文件(确实存在这个问题,时灵时不灵,很奇怪),那么请将name字段设置为不同的值,这样可以收到请求端同一上传批次的所有文件。