在移动端应用开发中,附件上传是一个非常常见的场景,例如上传身份证照片、合同 PDF、截图凭证等。在 uniapp 中,我们可以通过 uni.chooseImage
、uni.uploadFile
、以及 <image>
、WebView 或 PDF.js 等方式来实现 上传 + 回显 的完整流程。本文将以“上传照片和 PDF 并回显展示”为例,封装一个通用组件并提供调用示例。
一、业务场景
- 用户需要在页面中上传 图片 或 PDF 文件;
- 上传成功后,在页面上直接显示缩略图或文件信息;
- 支持点击图片预览,点击 PDF 打开在线阅读。
二、附件上传组件设计
我们可以创建一个通用组件 AttachmentUpload.vue
,用于统一处理:
- 照片选择(支持相册和拍照);
- PDF 文件选择(通过
uni.chooseFile
); - 文件上传到服务器;
- 回显(展示缩略图或文件名 + PDF 图标)。
三、组件实现
<template><view class="attachment-upload"><!-- 上传按钮 --><view class="upload-btn" @click="chooseFile"><text>上传附件</text></view><!-- 已上传附件展示 --><view class="file-list"><view v-for="(file, index) in fileList" :key="index" class="file-item"><!-- 图片预览 --><imagev-if="isImage(file.url)":src="file.url"class="preview-img"mode="aspectFill"@click="previewImage(file.url)"></image><!-- PDF 文件展示 --><view v-else class="pdf-preview" @click="openPdf(file.url)"><text class="pdf-icon">📄</text><text class="pdf-name">{{ file.name || 'PDF文件' }}</text></view></view></view></view>
</template><script>
export default {name: "AttachmentUpload",props: {value: {type: Array,default: () => []}},data() {return {fileList: this.value};},methods: {// 选择文件chooseFile() {const that = this;uni.showActionSheet({itemList: ["选择图片", "选择PDF文件"],success: (res) => {if (res.tapIndex === 0) {// 选择图片uni.chooseImage({count: 1,success: (chooseRes) => {that.uploadFile(chooseRes.tempFilePaths[0], "image");}});} else if (res.tapIndex === 1) {// 选择PDFuni.chooseFile({count: 1,type: "file",success: (chooseRes) => {const filePath = chooseRes.tempFiles[0].path;that.uploadFile(filePath, "pdf", chooseRes.tempFiles[0].name);}});}}});},// 文件上传uploadFile(filePath, fileType, fileName = "") {const that = this;uni.uploadFile({url: "https://example.com/upload", // 替换成你的服务端接口filePath: filePath,name: "file",formData: { fileType },success: (uploadRes) => {const data = JSON.parse(uploadRes.data);const fileUrl = data.url; // 服务端返回文件地址const newFile = { url: fileUrl, type: fileType, name: fileName };that.fileList.push(newFile);that.$emit("input", that.fileList);},fail: () => {uni.showToast({ title: "上传失败", icon: "none" });}});},// 判断是否为图片isImage(url) {return url.endsWith(".jpg") || url.endsWith(".png") || url.endsWith(".jpeg");},// 图片预览previewImage(url) {uni.previewImage({ urls: [url] });},// 打开 PDFopenPdf(url) {// H5:可用 <iframe> 或 PDF.js 打开// App:用 uni.openDocumentuni.downloadFile({url: url,success: (res) => {uni.openDocument({filePath: res.tempFilePath,fileType: "pdf"});}});}}
};
</script><style scoped>
.attachment-upload {padding: 10rpx;
}
.upload-btn {background-color: #007aff;color: #fff;padding: 20rpx;border-radius: 8rpx;text-align: center;margin-bottom: 20rpx;
}
.file-list {display: flex;flex-wrap: wrap;gap: 20rpx;
}
.file-item {width: 200rpx;height: 200rpx;border: 1px solid #ddd;border-radius: 8rpx;display: flex;align-items: center;justify-content: center;
}
.preview-img {width: 100%;height: 100%;border-radius: 8rpx;
}
.pdf-preview {display: flex;flex-direction: column;align-items: center;
}
.pdf-icon {font-size: 60rpx;
}
.pdf-name {font-size: 24rpx;color: #333;
}
</style>
四、父页面调用示例
<template><view class="page"><attachment-upload v-model="attachments"></attachment-upload><button @click="submit">提交</button></view>
</template><script>
import AttachmentUpload from "@/components/AttachmentUpload.vue";export default {components: { AttachmentUpload },data() {return {attachments: [] // 存储上传后的文件信息};},methods: {submit() {console.log("提交的附件:", this.attachments);// 提交到后端uni.request({url: "https://example.com/save",method: "POST",data: { attachments: this.attachments },success: () => {uni.showToast({ title: "提交成功", icon: "success" });}});}}
};
</script>
五、注意事项
- 后端接口
- 需要支持文件接收和返回上传后的 URL;
- 注意处理大文件 PDF 的上传。
- 兼容性
- H5 平台可能不支持
uni.openDocument
,建议用 PDF.js 或<iframe>
; - App 端可以直接使用
uni.openDocument
。
- 文件大小限制
- 可以通过
uni.chooseImage
/uni.chooseFile
的回调中检查size
; - 上传前做校验,避免过大文件导致失败。
六、总结
通过封装一个通用的 AttachmentUpload
组件,我们实现了 图片和 PDF 文件的上传、存储、回显和预览,并提供了父页面调用示例。在实际项目中,你可以进一步扩展支持 Word、Excel、视频 等格式,实现更强大的通用附件管理功能。