Tauri 实战:秒懂文件拖拽上传,轻松拿到绝对路径!

0 阅读1分钟

前言

最近碰到一个小需求,简单记录一下:我想在 Tauri 里实现 将文件拖拽到指定区域,并直接获取其绝对路径。一开始下意识地用了 Web 的常规做法,结果发现事情没那么简单。

Web 实现方案

首先,确保在 tauri.conf.json 中将窗口的 dragDropEnabled 设置为 false,防止系统层级的拖拽行为干扰。

然后,组件部分大致是这样写的:

<script setup lang="ts">
import { ref } from 'vue'

const dragenter = ref(false)

function handleDragEnter() {
  dragenter.value = true
}

function handleDragLeave() {
  dragenter.value = false
}

function handleDrop(event: DragEvent) {
  dragenter.value = false

  const files = event.dataTransfer?.files
  
  console.log(files)
}
</script>

<template>
  <div
    @dragenter.prevent="handleDragEnter"
    @dragleave.prevent="handleDragLeave"
    @dragover.prevent
    @drop.prevent="handleDrop"
  >
    拖动至此区域上传
  </div>
</template>

不过这个方案有个缺点:拿到的是文件对象而不是文件的绝对路径。虽然可以通过其它的方案解决,但我更希望能一步到位,直接拿到文件的路径,方便后续处理。

Tauri 实现方案

<script setup lang="ts">
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
import { onMounted, ref, useTemplateRef } from 'vue'

const dropRef = useTemplateRef('drop')
const dragenter = ref(false)

onMounted(() => {
  getCurrentWebviewWindow().onDragDropEvent(({ payload }) => {
    const { type } = payload

    if (type === 'over') {
      const { x, y } = payload.position

      if (dropRef.value) {
        const { left, right, top, bottom } = dropRef.value.getBoundingClientRect()

        const inBoundsX = x >= left && x <= right
        const inBoundsY = y >= top && y <= bottom

        dragenter.value = inBoundsX && inBoundsY
      }
    } else if (type === 'drop' && dragenter.value) {
      dragenter.value = false

      console.log('dropped', payload.paths)
    } else {
      dragenter.value = false
    }
  })
})
</script>

<template>
    <div ref="drop">
        拖动至此区域上传
    </div>
</template>

这样一来,不仅可以判断文件是否拖拽到了指定区域,还能直接获取绝对路径

iShot_2025-05-17_18.43.34-ezgif.com-video-to-gif-converter.gif