element-plus组件之Upload(1.0)

对应的Upload组件的网址为:Upload 上传 | Element Plus

在学习项目时,多次用到element-plus中的图片上传组件,这里就详细介绍一下,方便以后的学习和记忆。

一般在使用第三方的组件时,我们进行查看文档时,虽然官方提供了一些案例,但是有些属性和方法等不可能一一用实例展示出来,下面就对该组件存在的属性和方法等进行一一展示。

属性

 ①action

el-upload的action属性的设置就是上传的URL,与该属性对应使用的是auto-upload,该属性的值默认为true,说明只要你书写了action属性,就会默认进行上传【也就是像后端服务器发送请求】

 但是这样就存在了两个应用场景,一个是需要让改组件进行默认上传,就是一选择本地的资源文件,就上传到后端服务器。

另一个就是需要考虑到频繁修改图片或其他资源的场景,如果我们需要频繁的修改本地上传资源,那么我们就应该设置auto-upload为false,要不然频繁修改,频繁发送请求,就会造成服务器负担。

实例代码:

<template>
    <el-upload class="avatar-uploader" action="#" :show-file-list="false" :auto-upload="false"
        :on-change="handleChange">
        <img v-if="props.avatar" :src="uploadAvatar" class="avatar" />
        <el-icon v-else class="avatar-uploader-icon">
            <Plus />
        </el-icon>
    </el-upload>

</template>

该代码就是将upload单独做成一个组件,在用户选择图片等资源时,不向服务器发送请求,而在使用该组件的表单组件中,点击提交按钮或修改按钮后,再发送请求。

②headers

 另外,插入一个额外的点,封装的element封装的upload组件,自带选择文件的功能,只要你书写了以下代码:

 <el-upload
    list-type="picture-card"
    :auto-upload="false"
>

    </el-upload>

界面上的显示就会如下,点击就会出现文件选择,这里将list-type="picture-card"是为了让其显示,因为他存在默认样式,会让容器显示出来,要不然单独书写el-upload界面都看不到。

 然后,后续就以官方提供的实例进行介绍。

<template>
    <el-upload
      list-type="picture-card"
      v-model:file-list="fileList"
      class="upload-demo"
      action="#"
      :headers=obj
      method="put"
      name="Myfile"
      :data=data
      :show-file-list="true"
      :drag="false"
      
      multiple
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :limit="4"
      :on-exceed="handleExceed"
      :auto-upload="true"
    >
      <el-button type="primary">Click to upload</el-button>
      <template #tip>
        <div class="el-upload__tip">
          jpg/png files with a size less than 500KB.
        </div>
      </template>
    </el-upload>

这里的参数类型是 TypeScript 的定义方式,在Typescript中,Headers | Record<string, any> 是一个联合类型,表示该属性的值可以是 Headers 类型,也可以是 Record<string, any> 类型。 

Headers类型的设置可以如下:

let myHeaders = new Headers();
myHeaders.append("Content-Type", "image/jpeg");
<template>
  <el-upload
    :action="uploadUrl"
    :headers="uploadHeaders"
    :on-success="handleSuccess"
    :on-error="handleError"
  >
    <el-button slot="trigger" size="small" type="primary">点击上传</el-button>
  </el-upload>
</template>

<script>
export default {
  data() {
    return {
      uploadUrl: 'http://example.com/upload', // 替换为你的上传 URL
      uploadHeaders: {
        'Content-Type': 'multipart/form-data', // 设置内容类型
        'Authorization': 'Bearer your-token', // 如果需要认证令牌,可以在此处设置
        // 其他自定义头部信息
      }
    };
  },
  methods: {
    handleSuccess(response, file, fileList) {
      // 处理上传成功的逻辑
    },
    handleError(err, file, fileList) {
      // 处理上传失败的逻辑
    }
  }
};
</script>

 Record<string,any>类型也是一个对象,传递的键的类型为string,值的类型为any任意类型,在代码中我传递的是

  const obj=reactive({

    name:"mez"

  })

所以我们要想看到这个数据,需要发送请求,为了方便看到效果,我就设置了auto-upload=true。

我们可以看到我们写的数据,在请求头中发送给后端

③post

method设置上传的请求方法,默认为post请求 ,我们为了测试该属性,设置为put请求

 同样,在上面我们也可以看到发送的是put请求

④multiple

 

显而易见,就是在上传的时候支不支持多选文件,默认为false,不支持,我们设置为true试一试,还有就是,如果直接协商multiple就是设置为true,不写或设置为false就是不能多选的。

 下面是设置为false或者不填时

可以看到,多选时,就会默认调到第二次选择的图片

⑤data

 可以看出,和上面header的类型类似,也是需要一个对象类型

我们设置的data为

 

  const data=reactive({

    Mydata:'我是额外携带的数据'

  })

⑥name

我们在属性中设置name="Myfile",从上面也可以看出 ,在同样的位置

由于现在项目中很少用到cookie,所以 下面的属性就不再演示。

⑦show-file-list

 这个的效果就是是否显示你上传的文件列表,一般针对list-type="picture"的情况,可以列表显示你上传的文件名,因为picture-card这样的照片墙都直观的显示图片了,再设置这个属性没有效果

 

⑧drag

 这个就比较简单了,设置为true,就是可以直接拖拽文件到该组件,就默认上传了,设置为false就不启用拖拽功能。

⑨accept

指定上传的文件类型,加入我们设置为accept=".png",当然,也不止这一种设置方式,还有就是accept="image/jpeg,image/png"这样的设置方式,和file文件对象有关。

如果我们设置为accept=".png",默认选择的文件类型就是这样的

 

<template> <el-container class="layout-container-demo" style="height: 500px"> <el-header style="text-align: right; font-size: 12px"> <div class="toolbar"> <el-dropdown> <el-icon style="margin-right: 8px; margin-top: 1px"> <setting /> </el-icon> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @click="logOut()">退出登录</el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> <span>关宇航</span> </div> </el-header> <el-container> <el-aside width="200px"> <el-scrollbar> <el-menu :default-active="$route.path" class="el-menu-vertical-demo" :router="true"> <template v-for="(item, index) in menuList"> <el-menu-item v-if="isShow(item)" :index="index" :route="item.path">{{ item.label }}</el-menu-item> </template> </el-menu> </el-scrollbar> </el-aside> <el-main> <router-view /> </el-main> </el-container> </el-container> </template> <script setup> import { Menu as IconMenu, Setting } from '@element-plus/icons-vue' import useUserStore from '@/store/modules/user'; import { ElMessage } from 'element-plus' const userStore = useUserStore(); const router = useRouter(); const menuList = ref([]); function isShow(item) { return item?.aaaaa != 'asaf' } onMounted(() => { if (userStore.isLogin()) { setMenu(router.options.routes); } else { ElMessage.error(‘用户未登录,跳转至登录页面’); router.push(‘/’); } }); function setMenu(routes) { const menu = []; for (const route of routes) { if (route.children) { for (const child of route.children) { if (child.meta && child.meta.title) { const menuItem = { index: child.path, path: route.path + ‘/’ + child.path, label: child.meta.title, aaaaa: child.meta.aaaaa, }; menu.push(menuItem); } } } } menuList.value = menu } function logOut() { userStore.logOut(); ElMessage.success(‘已退出登录’); router.push(‘/’); } </script> <style scoped> .layout-container-demo .el-header { position: relative; background-color: var(--el-color-primary-light-7); color: var(--el-text-color-primary); } .layout-container-demo .el-aside { color: var(--el-text-color-primary); background: var(--el-color-primary-light-8); height: 100vh; } .layout-container-demo .el-menu { border-right: none; } .layout-container-demo .el-main { padding: 0; } .layout-container-demo .toolbar { display: inline-flex; align-items: center; justify-content: center; height: 100%; right: 20px; } </style> 我想把 用户管理画面,项目一览画面,项目管理画面 ,障碍票一览画面,障碍票详细画面 加入上部导航栏中,然后在丰富一下画面内容 用<template>画
07-23
<think>根据用户的问题和提供的引用内容,用户想知道在使用Element UI的`el-upload`组件时,是否能够获取文件的本地路径(即文件在用户计算机上的完整路径,如`C:\Users\...`)。 结合引用内容: - 引用[2]和[3]提到,通过`el-upload`组件的`on-change`事件可以获取到文件对象,然后使用`URL.createObjectURL(file.raw)`可以生成一个虚拟路径(blob URL),但这不是文件的真实本地路径。 - 引用[2]和[3]也指出,JavaScript无法获取本地文件的真实路径,这是出于浏览器安全限制。引用[2]中提到:“JavaScript无法获取本地文件路径,JavaScript不支持对本地资源的操作”。 - 引用[3]中提到尝试通过`document.getElementsByClassName("el-upload__input")[0].value`获取路径,但得到的只是文件名(如`test.jpg`),而不是完整路径。 因此,结论是:**出于浏览器安全原因,`el-upload`组件无法获取文件的真实本地路径(完整路径),只能获取文件名和生成用于预览的虚拟路径(blob URL)。** ### 详细解释: 1. **浏览器安全限制**:浏览器中的JavaScript运行在沙盒环境中,不允许访问用户文件系统的真实路径,以防止恶意脚本获取用户隐私信息。 2. **`el-upload`提供的信息**: - 在`on-change`事件中,我们可以获取到文件对象(File对象),其中包含文件名(`file.name`)、文件大小(`file.size`)、文件类型(`file.type`)等信息。 - 使用`URL.createObjectURL(file.raw)`可以生成一个临时URL,用于预览文件(如图片、PDF等),但这个URL并不是文件的真实路径,而是一个指向内存中文件的引用。 3. **获取文件名**:可以通过`file.name`获取文件名(不带路径),或者通过`document.querySelector('.el-upload__input').value`获取一个字符串(通常是文件名,但某些旧版浏览器可能包含路径,但现代浏览器出于安全考虑会去掉路径)。 ### 示例代码: ```html <template> <el-upload action="" :auto-upload="false" :on-change="handleChange" > <el-button>选择文件</el-button> </el-upload> </template> <script> export default { methods: { handleChange(file) { // 获取文件名(不包含路径) console.log('文件名:', file.name); // 生成用于预览的虚拟URL(blob URL) const url = URL.createObjectURL(file.raw); console.log('虚拟URL:', url); // 类似:blob:http://localhost:8080/550e8400-e29b-41d4-a716-446655440000 // 注意:这个虚拟URL并不是文件的真实路径 } } }; </script> ``` ### 替代方案: 如果应用需要获取文件的真实路径,可以考虑以下替代方案(但都有局限性): 1. **使用Electron或NW.js**:这些框架允许你构建桌面应用,通过Node.js的`path`模块可以获取文件完整路径。 2. **使用ActiveX控件(仅限IE)**:在旧版IE中可以通过ActiveX控件获取,但现代浏览器已不支持。 3. **通过后端中转**:将文件上传到服务器后,服务器可以返回文件路径(但这是服务器路径,不是客户端本地路径)。 ### 总结: 在标准的Web应用中,**无法通过`el-upload`组件获取用户文件的本地完整路径**,只能获取文件名和生成预览用的虚拟URL。这是由浏览器安全策略决定的,无法绕过。 --- ### 相关问题: 1. 如何在`el-upload`中实现文件上传前的格式验证? 2. 如何在使用`el-upload`时限制文件大小? 3. 如何为`el-upload`添加自定义的拖拽上传区域? 4. 如何实现`el-upload`的多文件选择功能?</think># Element UI 的 el-upload 组件获取文件路径指南 根据您的查询和提供的引用内容,我将详细解释 `el-upload` 组件获取文件路径的相关问题,并提供一个完整的解决方案。 ## 核心问题:el-upload 是否支持获取文件的本地路径? **答案:JavaScript 在浏览器环境中无法获取文件的真实本地路径(如 `C:\Users\...`),这是出于浏览器安全限制。但您可以通过 `el-upload` 获取文件的虚拟路径用于预览功能。** ### 关键要点: 1. **浏览器安全限制**:JavaScript 无法访问用户文件系统的真实路径(引用[2]) 2. **虚拟路径替代方案**:使用 `URL.createObjectURL()` 创建临时路径用于预览(引用[2]) 3. **Element UI 实现方式**:通过 `on-change` 事件获取文件对象(引用[1]) ## 完整实现方案 以下是一个使用 `el-upload` 获取文件信息并创建预览的完整示例: ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>el-upload 文件路径获取</title> <link rel="stylesheet" href="https://unpkg.com/element-plus/dist/index.css"> <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> <script src="https://unpkg.com/element-plus/dist/index.full.js"></script> <style> body { font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; background-color: #f5f7fa; padding: 20px; color: #333; } .container { max-width: 800px; margin: 0 auto; background: white; border-radius: 8px; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1); padding: 30px; } h1 { color: #409EFF; text-align: center; margin-bottom: 30px; } .upload-area { border: 2px dashed #dcdfe6; border-radius: 6px; padding: 20px; text-align: center; margin-bottom: 20px; background: #fafafa; transition: all 0.3s; cursor: pointer; } .upload-area:hover { border-color: #409EFF; background: #ecf5ff; } .file-info { background: #f0f9ff; border-left: 4px solid #409EFF; padding: 15px; margin: 20px 0; border-radius: 0 4px 4px 0; } .preview-container { margin-top: 20px; text-align: center; } .preview-image { max-width: 100%; max-height: 300px; border-radius: 4px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .info-grid { display: grid; grid-template-columns: 100px 1fr; gap: 10px; margin: 10px 0; } .info-label { font-weight: bold; color: #606266; } .info-value { color: #303133; word-break: break-all; } .action-buttons { display: flex; gap: 10px; margin-top: 20px; justify-content: center; } .security-note { background: #fff6f6; border-left: 4px solid #f56c6c; padding: 10px 15px; margin: 20px 0; border-radius: 0 4px 4px 0; font-size: 14px; } </style> </head> <body> <div id="app"> <div class="container"> <h1>el-upload 文件路径获取与预览</h1> <div class="security-note"> <p><strong>安全提示:</strong>由于浏览器安全限制,JavaScript 无法获取文件的真实物理路径(如 C:\Users\...),但可以获取文件的虚拟路径用于预览。</p> </div> <el-upload class="upload-area" :auto-upload="false" :on-change="handleFileChange" :show-file-list="false" :limit="1" accept="image/*,.pdf,.doc,.docx" > <div> <el-icon :size="50" color="#409EFF"><UploadFilled /></el-icon> <p>点击或拖拽文件到此处</p> <p class="el-upload__tip">支持图片、PDF、Word文档等格式</p> </div> </el-upload> <div v-if="selectedFile"> <div class="file-info"> <h3>文件信息</h3> <div class="info-grid"> <div class="info-label">文件名:</div> <div class="info-value">{{ selectedFile.name }}</div> <div class="info-label">文件类型:</div> <div class="info-value">{{ selectedFile.type || '未知' }}</div> <div class="info-label">文件大小:</div> <div class="info-value">{{ formatFileSize(selectedFile.size) }}</div> <div class="info-label">虚拟路径:</div> <div class="info-value">{{ filePath }}</div> </div> </div> <div class="preview-container"> <h3>文件预览</h3> <div v-if="isImage"> <img :src="filePath" class="preview-image" alt="文件预览"> </div> <div v-else-if="isPDF"> <div style="background: #f0f9ff; padding: 20px; border-radius: 4px;"> <el-icon :size="50" color="#409EFF"><Document /></el-icon> <p>PDF 文件预览 (路径: {{ filePath }})</p> </div> </div> <div v-else> <div style="background: #f0f9ff; padding: 20px; border-radius: 4px;"> <el-icon :size="50" color="#409EFF"><Document /></el-icon> <p>不支持预览此文件类型</p> </div> </div> </div> <div class="action-buttons"> <el-button type="primary" @click="simulateUpload">模拟上传</el-button> <el-button type="danger" @click="clearFile">清除文件</el-button> </div> </div> <div v-else> <el-alert title="尚未选择文件" type="info" show-icon :closable="false"> 请点击上方区域选择文件 </el-alert> </div> </div> </div> <script> const { createApp, ref } = Vue; const { ElUpload, ElButton, ElIcon, ElAlert } = ElementPlus; const app = createApp({ setup() { const selectedFile = ref(null); const filePath = ref(''); const isImage = ref(false); const isPDF = ref(false); // 处理文件选择变化 const handleFileChange = (file) => { // 保存文件对象 selectedFile.value = file.raw; // 创建文件虚拟路径 filePath.value = URL.createObjectURL(file.raw); // 检查文件类型 isImage.value = file.raw.type.startsWith('image/'); isPDF.value = file.raw.type === 'application/pdf'; // 尝试获取input值(仅包含文件名) try { const input = document.querySelector('.el-upload__input'); console.log('Input value:', input.value); // 仅文件名,无路径 } catch (e) { console.log('无法访问input元素:', e.message); } }; // 清除文件 const clearFile = () => { if (filePath.value) { URL.revokeObjectURL(filePath.value); // 释放对象URL } selectedFile.value = null; filePath.value = ''; isImage.value = false; isPDF.value = false; }; // 模拟上传 const simulateUpload = () => { if (!selectedFile.value) return; // 在实际应用中,这里会发送文件到服务器 console.log('模拟上传文件:', selectedFile.value.name); // 显示成功消息 ElMessage.success(`文件 "${selectedFile.value.name}" 上传成功`); }; // 格式化文件大小 const formatFileSize = (bytes) => { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; return { selectedFile, filePath, isImage, isPDF, handleFileChange, clearFile, simulateUpload, formatFileSize }; } }); app.component(ElUpload.name, ElUpload); app.component(ElButton.name, ElButton); app.component(ElIcon.name, ElIcon); app.component(ElAlert.name, ElAlert); app.mount('#app'); </script> </body> </html> ``` ## 关键实现解析 ### 1. 获取文件对象 通过 `on-change` 事件处理函数获取文件对象: ```javascript handleFileChange(file) { selectedFile.value = file.raw; // 获取原始文件对象 } ``` ### 2. 创建虚拟路径 使用 `URL.createObjectURL()` 生成临时URL用于预览: ```javascript filePath.value = URL.createObjectURL(file.raw); ``` ### 3. 文件类型检测 根据文件类型显示不同的预览内容: ```javascript isImage.value = file.raw.type.startsWith('image/'); isPDF.value = file.raw.type === 'application/pdf'; ``` ### 4. 内存管理 不再需要时释放对象URL: ```javascript URL.revokeObjectURL(filePath.value); ``` ### 5. 获取输入值(仅文件名) 虽然无法获取完整路径,但可以获取文件名: ```javascript const input = document.querySelector('.el-upload__input'); console.log('Input value:', input.value); // 例如: "example.jpg" ``` ## 浏览器安全限制说明 JavaScript 在浏览器中运行时受到严格的安全限制: 1. **无法访问真实路径**:浏览器不允许脚本获取用户文件系统的真实路径 2. **虚拟路径替代**:`URL.createObjectURL()` 创建的是临时 blob URL 3. **输入值限制**:`<input type="file">` 元素的 `value` 属性仅返回文件名,不包含路径 ## 替代方案 如果需要获取完整路径,可以考虑: 1. **桌面应用框架**:使用 Electron 或 NW.js 构建桌面应用 2. **浏览器插件**:开发浏览器扩展获取额外权限 3. **ActiveX 控件(仅限旧版IE)**:不推荐,已过时 ## 相关问题 1. **如何在 `el-upload` 中实现文件上传前的格式验证?** 使用 `before-upload` 钩子函数进行验证,返回 `false` 阻止上传 2. **如何在使用 `el-upload` 时限制文件大小?** 在 `before-upload` 钩子中检查 `file.size`,超过限制则提示并取消上传 3. **如何为 `el-upload` 添加自定义的拖拽上传区域?** 使用 `slot="trigger"` 自定义触发区域,结合 CSS 实现拖拽样式 4. **如何实现 `el-upload` 的多文件选择功能?** 设置 `multiple` 属性并调整 `limit` 值为允许的最大文件数 5. **如何获取文件夹路径和结构?** 使用 `webkitdirectory` 属性(仅限 Chrome)或考虑桌面应用方案(引用[4])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mez_Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值