<template>
  <view class="file-upload-container">
    <button type="primary" @click="chooseFile">选择文件</button>
    <view class="file-info" v-if="fileInfo.name">
      <text>选中文件:{{ fileInfo.name }}</text>
      <text>文件大小:{{ formatFileSize(fileInfo.size) }}</text>
    </view>
    <button type="success" @click="uploadFile" v-if="fileInfo.path" style="margin-top: 10px;">上传文件</button>
    <view class="progress" v-if="progress > 0 && progress < 100">
      <text>上传进度:{{ progress }}%</text>
    </view>
    <view class="result success" v-if="uploadResult === 'success'">
      <text>文件上传成功!</text>
    </view>
    <view class="result error" v-if="uploadResult === 'error'">
      <text>文件上传失败:{{ errorMsg }}</text>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      fileInfo: {},
      progress: 0,
      uploadResult: null,
      errorMsg: ''
    };
  },
  methods: {
    /**
     * 选择文件(适配微信小程序,替换uni.chooseFile)
     */
    chooseFile() {
      this.resetState();
      
      // 区分平台:H5用uni.chooseFile,微信小程序用wx.chooseMessageFile
      const system = uni.getSystemInfoSync();
      if (system.platform === 'h5') {
        // H5端仍使用uni.chooseFile
        uni.chooseFile({
          count: 1,
          extension: [],
          success: (res) => {
            this.fileInfo = res.tempFiles[0];
          },
          fail: (err) => {
            uni.showToast({ title: '选择文件失败', icon: 'none' });
            console.error(err);
          }
        });
      } else if (system.platform === 'mp-weixin') {
        // 微信小程序端使用原生API wx.chooseMessageFile
        wx.chooseMessageFile({
          count: 1, // 最多选择1个文件
          type: 'file', // 只选择文件(不选图片/视频)
          success: (res) => {
            // res.tempFiles是文件数组,结构与uni.chooseFile返回的一致
            this.fileInfo = res.tempFiles[0];
            console.log('选中文件:', this.fileInfo);
          },
          fail: (err) => {
            uni.showToast({ title: '选择文件失败', icon: 'none' });
            console.error('选择文件失败:', err);
          }
        });
      } else {
        // App端等其他平台,仍尝试使用uni.chooseFile(若仍报错可替换为其他原生API)
        uni.chooseFile({
          count: 1,
          extension: [],
          success: (res) => {
            this.fileInfo = res.tempFiles[0];
          },
          fail: (err) => {
            uni.showToast({ title: '选择文件失败', icon: 'none' });
            console.error(err);
          }
        });
      }
    },

    /**
     * 上传文件(逻辑不变,仍使用uni.uploadFile)
     */
    uploadFile() {
      if (!this.fileInfo.path) {
        uni.showToast({ title: '请先选择文件', icon: 'none' });
        return;
      }

      uni.uploadFile({
        url: 'https://your-domain.com/api/upload', // 替换为你的后端接口
        filePath: this.fileInfo.path,
        name: 'file',
        formData: {
          'user_id': '123',
          'file_type': 'document'
        },
        header: {
          'Authorization': 'Bearer ' + uni.getStorageSync('token')
        },
        progress: (res) => {
          this.progress = Math.floor(res.progress);
        },
        success: (res) => {
          this.progress = 100;
          let result = {};
          try {
            result = JSON.parse(res.data);
          } catch (e) {
            result = res.data;
          }

          if (res.statusCode === 200 && result.code === 0) {
            this.uploadResult = 'success';
            uni.showToast({ title: '上传成功', icon: 'success' });
          } else {
            this.uploadResult = 'error';
            this.errorMsg = result.msg || '上传失败';
            uni.showToast({ title: this.errorMsg, icon: 'none' });
          }
        },
        fail: (err) => {
          this.uploadResult = 'error';
          this.errorMsg = '网络错误或服务器异常';
          uni.showToast({ title: this.errorMsg, icon: 'none' });
          console.error(err);
        }
      });
    },

    // 格式化文件大小(逻辑不变)
    formatFileSize(size) {
      if (size < 1024) {
        return size + ' B';
      } else if (size < 1024 * 1024) {
        return (size / 1024).toFixed(2) + ' KB';
      } else {
        return (size / (1024 * 1024)).toFixed(2) + ' MB';
      }
    },

    // 重置状态(逻辑不变)
    resetState() {
      this.fileInfo = {};
      this.progress = 0;
      this.uploadResult = null;
      this.errorMsg = '';
    }
  }
};
</script>

<style scoped>
/* 样式与之前一致,无需修改 */
.file-upload-container {
  padding: 20px;
}
.file-info {
  margin: 10px 0;
  line-height: 1.6;
}
.progress {
  margin: 10px 0;
  color: #007aff;
}
.result {
  margin: 10px 0;
  padding: 10px;
  border-radius: 5px;
}
.success {
  background-color: #f0f9ff;
  color: #00b42a;
}
.error {
  background-color: #fff2f0;
  color: #f53f3f;
}
</style>

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐