用element的el-upload实现文件上传

本文详细介绍了一个使用Element UI组件实现的前端文件上传功能,包括限制上传文件的数量、类型和大小,以及上传过程中的预览、移除操作。同时,介绍了如何通过后端处理文件上传,包括本地上传和七牛云上传两种方式。

前端部分

limit是设置上传数量

<el-upload class="upload-demo" 
    :action="uploadAction" 
    :on-preview="handlePreview" 
    :on-remove="handleRemove"
    :before-remove="beforeRemove" multiple 
    :limit="1" 
    :on-exceed="handleExceed" 
    ref="upload" 
    :file-list="editForm.fileList"
    :http-request="getFile" 
    :before-upload="beforeUploadFile">
    <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
    <el-button style="margin-left: 10px;" size="small" type="success" @click="uploadFile">上传到服务器</el-button>
    <div slot="tip" class="el-upload__tip">只能上传后缀是txt的文件,且不超过1M</div>
  </el-upload>

参数

data() {
      return {
      	editForm: {
   		  file: {},
          fileList: []
        }
      }
}

方法

handleRemove(file, fileList) {
  console.log(file, fileList);
  this.editForm.file = {};
},
handlePreview(file) {
  console.log(file);
},
handleExceed(files, fileList) {
  this.$message.warning(`只能上传一个文件`);
},
beforeRemove(file, fileList) {
  return this.$confirm(`确定移除 ${ file.name }?`);
},
//上传文件限制
beforeUploadFile(file) {
  console.log(file)
  let extension = file.name.substring(file.name.lastIndexOf('.') + 1)
  let size = file.size / 1024 / 1024
  if (extension !== 'txt') {
    this.$refs.upload.clearFiles();
    this.$message.warning('只能上传后缀是txt的文件');
  }
  if (size > 1) {
    this.$refs.upload.clearFiles();
    this.$message.warning('文件大小不得超过1M');
  }
},
//文件上传
getFile(item) {
  console.log(item.file)
  this.editForm.file = item.file
},
uploadFile() {
  if (this.editForm.file.name == undefined) {
    this.$refs.upload.clearFiles();
    this.$message.warning('请选择文件');
    return;
  }
  let extension = this.editForm.file.name.substring(this.editForm.file.name.lastIndexOf('.') + 1)
  let size = this.editForm.file.size / 1024 / 1024
  if (extension !== 'txt') {
    this.$refs.upload.clearFiles();
    this.$message.warning('请选择文件');
    return;
  }
  if (size > 1) {
    this.$refs.upload.clearFiles();
    this.$message.warning('请选择文件');
    return;
  }
  let formData = new FormData()
  console.log(this.editForm.file)
  formData.append('fileName', this.editForm.file.name)
  formData.append('file', this.editForm.file)

  let config = {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  }
  console.log(formData);

  uploadFile(formData, config).then(response => {
    this.editForm.impowerurl = response.filePath
    // this.$refs.upload.clearFiles();
  })
  this.editForm.file = {};
  this.editForm.fileList = [];
},

js

export function uploadFile(data) {
  return request({
    url: '**',
    method: 'POST',
    data
  })
}

后端

1、本地上传

@PostMapping("/uploadFile")
public R uploadFile(@RequestParam("file") MultipartFile file) {
    String fileName = file.getOriginalFilename();
    if (StringUtils.isEmpty(fileName)) {
        return R.error("上传文件为空");
    }
    // 文件上传路径
    String templatePath = "F:/FilePackage/";

   // 获取文件的后缀名
   String suffixName = fileName.substring(fileName.lastIndexOf("."));

   //获取文件名
   String prefixName = fileName.substring(0, fileName.lastIndexOf("."));

   // 解决中文问题,liunx 下中文路径,图片显示问题
   fileName = UUID.randomUUID() + suffixName;
   File dests = new File(templatePath);
   File dest = new File(dests, prefixName + File.separator + fileName);
     //文件上传-覆盖
     try {
         // 检测是否存在目录
         if(!dests.exists()){
            dests.mkdirs();
        }
        // getParentFile获取上一级
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
         file.transferTo(dest);
         //文件存储路径
         String filePath = templatePath+prefixName+"/"+fileName;

         return R.ok("上传成功!").put("filePath",filePath);
     } catch (Exception e) {
         return R.error("上传失败,文件内容为空");
     }
}

2、七牛云上传

    @ApiOperation("上传文件")
    @PostMapping(value = "/uploadFile")
    public R uploadFile(@RequestParam("file") MultipartFile file) {
        String ak = "*****************";
        String sk = "*****************";
        String bucketname = "**";
        String url = "http://**/";
        if(file.isEmpty()) {
            return R.error(400,"文件为空,上传失败!");
        }
        // 获取文件的后缀名
        String suffixName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")+1);
        if(!suffixName.equals("jpg") && !suffixName.equals("png")){
            return R.error(400,"请上传jpg,png文件");
        }
        //文件后缀
        String fileExt = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1).toLowerCase();

        String fileName = UUID.randomUUID().toString().replaceAll("-", "") + "." + fileExt;

        // 密钥配置
        Auth auth = Auth.create(ak, sk);
        // 构造一个带指定Zone对象的配置类,不同的七云牛存储区域调用不同的zone
        Configuration cfg = new Configuration(Zone.zone2());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);

        // 调用put方法上传
        Response res = null;
        try {
            res = uploadManager.put(file.getBytes(), fileName, auth.uploadToken(bucketname));

            // 打印返回的信息
            if (res.isOK() && res.isJson()) {
                // 返回这张存储照片的地址
                String fileUrl = url + JSONObject.parseObject(res.bodyString()).get("key");
                return R.ok().put("filePath",fileUrl);
            } else {
                return R.error(400,"七牛云异常");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.error(400,"七牛云异常");
    }

依赖

        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>[7.2.0, 7.2.99]</version>
        </dependency>
<think>根据用户的问题,用户在使用Element UI的el-upload组件上传文件后遇到了文件名不显示的问题。用户希望得到解决方案。 从用户提供的引用内容来看,引用[1]和引用[2]都提到了在`handleChange`方法中通过创建新的File对象来修改文件名,并替换掉原始文件的`raw`属性。同时,为了确保组件内部不报错,还手动添加了`uid`属性。 用户的问题可能是由于在修改文件名后,组件的显示逻辑没有更新导致的。但根据引用中的代码,他们通过替换`file.raw`并手动触发上传(`this.$refs.upload.submit()`)来解决问题。 然而,用户现在遇到的是上传后文件名不显示的问题。这可能是因为在修改文件后,组件的文件列表没有正确更新。因此,我们需要确保在修改文件后,组件能够正确地显示新的文件名。 解决方案可以包括: 1. 确保在`handleChange`方法中修改文件后,更新组件的文件列表。但是注意,el-upload组件在文件变化时会自动更新文件列表,所以可能不需要手动更新。 2. 检查是否在模板中正确绑定了文件列表,并显示文件名。 根据Element UI的文档,el-upload组件会通过`file-list`属性来绑定文件列表,并且可以通过`scoped slot`来自定义显示。如果用户没有正确使用插槽来显示文件名,可能会导致不显示。 因此,我们可以从以下两个方面考虑: - 检查是否在模板中使用了`file-list`属性,并且是否在插槽中正确显示了文件名。 - 在修改文件名后,确保文件列表中的文件对象已经更新。 另外,引用[2]中还提到,文件名中如果包含特殊符号可能会导致上传报错,因此他们通过正则表达式去除了特殊符号。但用户的问题是不显示,所以可能不是特殊符号的问题,但这也可能是导致不显示的一个原因(比如文件名含有非法字符导致显示异常)。 下面,我们将提供一个可能的解决方案,包括如何修改文件名并确保正确显示。 ### 解决方案 #### 1. 修改文件名并更新文件列表 在`handleChange`方法中,我们按照引用的方式创建一个新的File对象,并替换`file.raw`。但是,需要注意的是,el-upload组件的文件列表是内部维护的,我们修改`file.raw`后,组件应该会自动更新。如果仍然不显示,我们可以尝试强制更新组件。 另外,我们可以通过使用`file-list`属性绑定一个数组,然后手动更新这个数组来确保文件名显示。 #### 2. 在模板中正确显示文件名 在el-upload组件中,默认情况下,它会显示文件名。但是,如果用户使用了自定义模板(插槽),则需要确保在插槽中显示文件名。 #### 示例代码 下面是一个示例,展示如何修改文件名并确保显示: ```vue <template> <div> <el-upload ref="upload" action="https://jsonplaceholder.typicode.com/posts/" :auto-upload="false" :on-change="handleChange" :file-list="fileList" <!-- 绑定fileList数组 --> > <el-button slot="trigger" size="small" type="primary">选取文件</el-button> <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> </el-upload> </div> </template> <script> export default { data() { return { fileList: [] // 初始化文件列表 }; }, methods: { handleChange(file, fileList) { // 修改文件名,例如添加后缀 let fileName = file.name + '.suffix'; // 去除特殊字符(可选) // fileName = fileName.replace(/[^\w\.-]/g, ''); // 创建新的File对象 let newFile = new File([file.raw], fileName, { type: file.raw.type }); // 手动设置uid,防止组件内部报错 newFile.uid = file.uid; // 由于fileList是只读的,我们需要创建一个新的数组来更新 // 找到当前修改的文件在列表中的位置 const index = fileList.findIndex(f => f.uid === file.uid); if (index !== -1) { // 创建一个新的文件对象,用于替换原文件对象 const newFileObj = { ...fileList[index], name: fileName, // 更新文件名 raw: newFile // 更新raw }; // 更新整个文件列表 const updatedFileList = [...fileList]; updatedFileList.splice(index, 1, newFileObj); this.fileList = updatedFileList; // 更新绑定的fileList } // 如果需要自动上传,可以调用submit // this.$refs.upload.submit(); } } }; </script> ``` 在上面的代码中: - 我们使用`file-list`属性绑定了一个数组`fileList`,这样我们可以控制文件列表的显示。 - 在`handleChange`方法中,我们修改文件名,并创建新的File对象。 - 然后,我们更新文件列表中对应文件的`name`和`raw`属性,并重新设置整个文件列表(因为Vue的响应式要求,我们需要创建一个新的数组)。 这样,文件名应该会正确显示。 #### 注意事项 - 如果不需要立即上传,可以注释掉`this.$refs.upload.submit()`,这样文件会在用户点击上传按钮时再上传。 - 去除特殊符号的正则表达式可以根据需要添加。 ### 相关问题 1. 如何限制el-upload上传文件的类型和大小? 2. el-upload组件如何实现拖拽上传? 3.el-upload中如何实现文件上传并控制并发?</think>### Element UI el-upload 上传文件后文件名不显示问题解决方案 在使用 Element UI 的 `el-upload` 组件时,文件名不显示通常是由于文件对象的 `name` 属性未正确设置或组件渲染机制导致的。以下是具体原因和解决方案: #### 原因分析 1. **文件对象未正确更新**:修改文件名后未更新 `file.raw` 对象的 `name` 属性 2. **UID 冲突**:新建 `File` 对象时丢失了原文件的 `uid` 属性 3. **特殊字符问题**:文件名包含特殊符号导致渲染异常 4. **响应式更新失败**:Vue 无法检测到文件对象的深层属性变化 #### 解决方案 通过修改 `handleChange` 方法,创建新文件对象并保留必要属性: ```vue <template> <el-upload ref="upload" action="/api/upload" :auto-upload="false" :on-change="handleChange" :file-list="fileList"> <!-- 上传区域 --> </el-upload> </template> <script> export default { data() { return { fileList: [] // 绑定文件列表 } }, methods: { handleChange(file, fileList) { // 1. 清理特殊字符(可选) const cleanName = file.name.replace(/[^\w\.-]/g, ''); // 2. 创建新文件对象(保留原类型) const newFile = new File( [file.raw], `${cleanName}${this.extendName}`, { type: file.raw.type } ); // 3. 保留关键属性 newFile.uid = file.uid; // 必须保留UID // 4. 更新文件列表 const updatedList = fileList.map(item => item.uid === file.uid ? { ...item, raw: newFile, name: newFile.name } : item ); // 5. 触发视图更新 this.fileList = updatedList; // 6. 手动触发上传(可选) this.$nextTick(() => { this.$refs.upload.submit(); }); } } } </script> ``` #### 关键修改说明 1. **文件清理**(可选) ```javascript const cleanName = file.name.replace(/[^\w\.-]/g, ''); // 移除非法字符[^2] ``` 2. **正确创建 File 对象** ```javascript new File([file.raw], newName, { type: file.raw.type }) // 保留原始MIME类型 ``` 3. **保留 UID** ```javascript newFile.uid = file.uid; // 防止组件内部报错[^1] ``` 4. **响应式更新** ```javascript this.fileList = updatedList; // 强制触发视图更新 ``` #### 注意事项 1. 使用 `:file-list="fileList"` 绑定响应式数据 2. 修改后通过 `this.$nextTick()` 确保 DOM 更新完成 3. 特殊字符处理可根据实际需求调整正则表达式 4. 如果不需要即时上传,可移除 `submit()` 调用 > 此方案避免了使用 FormData 的复杂性,直接通过修改文件对象实现[^1]。通过保留 UID 和正确更新文件列表,确保组件能正常渲染文件名。 --- ### 相关问题 1. **如何限制 el-upload 上传文件的类型和大小?** [提示:使用 `accept` 属性和 `before-upload` 钩子] 2. **el-upload 如何实现拖拽上传和多文件选择?** [提示:`drag` 属性和 `multiple` 属性配置] 3. **上传过程中如何显示进度条和取消上传?** [提示:`on-progress` 事件和 `abort()` 方法的使用] 4. **如何自定义 el-upload 的文件列表展示样式?** [提示:使用 `scoped slot` 自定义模板] 5. **服务器返回错误时如何优雅处理上传失败?** [提示:`on-error` 钩子和错误提示集成] [^1]: 通过创建新 File 对象修改文件名而不使用 FormData [^2]: 文件名特殊字符处理可避免上传报错
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值