简介
公司新需求,对电脑硬盘的文件进行访问操作,并显示到视图上,要想访问电脑硬盘文件,浏览器是没有权限可以进行访问的,必须是桌面应用,也就是需要使用到electron。如果只是访问项目内的文件内容,就不用使用electron。
完整代码在结尾处,可直接复制使用。
一、安装node
确保提前安装了fs
模块,你可以使用以下命令进行安装:
npm install --save fs
二、引入fs方法进行访问文件目录并显示到视图
通过fs的readdirSync根据路径获取到文件夹目录数据,循环获取到的数据再通过fs的statSync对目录内容进行分类。
注意:如果访问不了,要确定打开了文件权限,允许读写其内容才行。
<script setup lang="ts">
import { ref } from "vue";
import cataLogue from "../assets/image/cata-logue.png";//文件夹图片
import text from "../assets/image/text.png";//文件图片
import back from "../assets/image/back.png";//返回上一级图片
const fs = require("fs"); // 引入node的fs模块
const items: any = ref([]);
let directoryPath = "/Users/xxx/xxx/xxx"; // 替换为实际的目录路径
// 获取文件夹目录并进行分类
getCatalogue(directoryPath);
async function getCatalogue(path: any) {
try {
// 通过fs的readdirSync获取到指定路径的文件夹目录数据
const filesList = fs.readdirSync(path);
// 通过循环使用fs的statSync判断目录中那些为文件和文件夹
const itemsList = filesList.map((fileName: any) => {
const filePath = `${path}/${fileName}`;
const stats = fs.statSync(filePath);
return {
name: fileName,
isDirectory: stats.isDirectory(),
};
});
// 将分类好的数据赋值items反显到视图上
items.value = itemsList;
} catch (err) {
console.error(err);
}
return Promise.resolve();
}
</script>
当获取到了文件夹目录数据后通过循环数据内容反显到视图上
<template>
<div style="width: 100%; height: 100%">
<h1>文件夹目录</h1>
<img v-if="isShow" style="width: 50px" :src="back" @click="backUpLevel" />
<div class="box">
<span
class="logue-content"
v-for="item in items"
:key="item.name"
@dblclick="openItem(item)"
>
<img :src="item.isDirectory ? text : cataLogue" />
<div>{{ item.name }}</div>
</span>
</div>
</div>
</template>
这样就可以在视图上看到内容了。
这个时候已经完成了展示,开始实现访问下一级已经返回。
三、访问下一级目录
template里面咱们循环数据时,有两个方法分别是进入下一级目录的openItem和返回上一级的backUpLevel。
通过拼接地址重新调用getCateLogue() 获取到下一级数据并反显
<script setup lang="ts">
import { ref } from "vue";
import cataLogue from "../assets/image/cata-logue.png";
import text from "../assets/image/text.png";
import back from "../assets/image/back.png";
const fs = require("fs"); // 引入node的fs模块
const items: any = ref([]);
const fileContent: any = ref("");
const isShow: any = ref(false);
const fileDataShow: any = ref(false);
let directoryPath = "/Users/sanyuanui/Desktop/electronLocal"; // 替换为实际的目录路径
// 获取文件夹目录并进行分类
getCatalogue(directoryPath);
async function getCatalogue(path: any) {
try {
// 通过fs的readdirSync获取到指定路径的文件夹目录数据
const filesList = fs.readdirSync(path);
// 通过循环使用fs的statSync判断目录中那些为文件和文件夹
const itemsList = filesList.map((fileName: any) => {
const filePath = `${path}/${fileName}`;
const stats = fs.statSync(filePath);
return {
name: fileName,
isDirectory: stats.isDirectory(),
};
});
// 将分类好的数据赋值items反显到视图上
items.value = itemsList;
} catch (err) {
console.error(err);
}
return Promise.resolve();
}
// 通过双击事件进入下一级目录
const openItem = (item: any) => {
// 拼接下一级的地址并进行访问
directoryPath = `${directoryPath}/${item.name}`;
// 当双击的是文件夹时
if (item.isDirectory) {
isShow.value = true;
getCatalogue(directoryPath);
} else {
// 点击的是文件时
fileDataShow.value = true;
getFileData(directoryPath);
}
};
// 返回上一级
function backUpLevel() {
directoryPath = directoryPath.split("/").slice(0, -1).join("/");
getCatalogue(directoryPath);
if (directoryPath === "/Users/sanyuanui/Desktop/electronLocal") {
isShow.value = false;
}
}
</script>
四、获取文件信息,反显到textarea上 即可进行对文件操作
<script setup lang="ts">
import { ref } from "vue";
import cataLogue from "../assets/image/cata-logue.png";
import text from "../assets/image/text.png";
import back from "../assets/image/back.png";
const fs = require("fs"); // 引入node的fs模块
const items: any = ref([]);
const fileContent: any = ref("");
const isShow: any = ref(false);
const fileDataShow: any = ref(false);
let directoryPath = "/Users/sanyuanui/Desktop/electronLocal"; // 替换为实际的目录路径
// 获取文件夹目录并进行分类
getCatalogue(directoryPath);
async function getCatalogue(path: any) {
try {
// 通过fs的readdirSync获取到指定路径的文件夹目录数据
const filesList = fs.readdirSync(path);
// 通过循环使用fs的statSync判断目录中那些为文件和文件夹
const itemsList = filesList.map((fileName: any) => {
const filePath = `${path}/${fileName}`;
const stats = fs.statSync(filePath);
return {
name: fileName,
isDirectory: stats.isDirectory(),
};
});
// 将分类好的数据赋值items反显到视图上
items.value = itemsList;
} catch (err) {
console.error(err);
}
return Promise.resolve();
}
// 通过双击事件进入下一级目录
const openItem = (item: any) => {
// 拼接下一级的地址并进行访问
directoryPath = `${directoryPath}/${item.name}`;
// 当双击的是文件夹时
if (item.isDirectory) {
isShow.value = true;
getCatalogue(directoryPath);
} else {
// 点击的是文件时
fileDataShow.value = true;
getFileData(directoryPath);
}
};
// 返回上一级
function backUpLevel() {
directoryPath = directoryPath.split("/").slice(0, -1).join("/");
getCatalogue(directoryPath);
if (directoryPath === "/Users/sanyuanui/Desktop/electronLocal") {
isShow.value = false;
}
}
// 获取文件信息
async function getFileData(path: string) {
try {
// 通过fs的readFileSync访问传输进来的地址文件数据
const content = fs.readFileSync(path, { encoding: "utf-8" });
// 讲文件数据反显到视图上
fileContent.value = content;
} catch (error) {
console.error(error);
}
}
// 保存文件内容
function saveFile() {
try {
fs.writeFileSync(directoryPath, fileContent.value, { encoding: "utf-8" });
fileDataShow.value = false;
directoryPath = directoryPath.split("/").slice(0, -1).join("/");
console.log("文件保存成功!");
} catch (error) {
console.error(error);
}
}
</script>
五、完整代码内容 复制粘贴即可使用(图片需更换地址)
<template>
<div style="width: 100%; height: 100%">
<h1>文件夹目录</h1>
<img v-if="isShow" style="width: 50px" :src="back" @click="backUpLevel" />
<div class="box">
<span
class="logue-content"
v-for="item in items"
:key="item.name"
@dblclick="openItem(item)"
>
<img :src="item.isDirectory ? text : cataLogue" />
<div>{{ item.name }}</div>
</span>
</div>
<!-- 文件夹内容 -->
<div v-if="fileDataShow">
<textarea v-model="fileContent" rows="10" cols="50"></textarea>
<button style="background-color: #fff" @click="saveFile">保存</button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import cataLogue from "../assets/image/cata-logue.png";
import text from "../assets/image/text.png";
import back from "../assets/image/back.png";
const fs = require("fs"); // 引入node的fs模块
const items: any = ref([]);
const fileContent: any = ref("");
const isShow: any = ref(false);
const fileDataShow: any = ref(false);
let directoryPath = "/Users/sanyuanui/Desktop/electronLocal"; // 替换为实际的目录路径
// 获取文件夹目录并进行分类
getCatalogue(directoryPath);
async function getCatalogue(path: any) {
try {
// 通过fs的readdirSync获取到指定路径的文件夹目录数据
const filesList = fs.readdirSync(path);
// 通过循环使用fs的statSync判断目录中那些为文件和文件夹
const itemsList = filesList.map((fileName: any) => {
const filePath = `${path}/${fileName}`;
const stats = fs.statSync(filePath);
return {
name: fileName,
isDirectory: stats.isDirectory(),
};
});
// 将分类好的数据赋值items反显到视图上
items.value = itemsList;
} catch (err) {
console.error(err);
}
return Promise.resolve();
}
// 通过双击事件进入下一级目录
const openItem = (item: any) => {
// 拼接下一级的地址并进行访问
directoryPath = `${directoryPath}/${item.name}`;
// 当双击的是文件夹时
if (item.isDirectory) {
isShow.value = true;
getCatalogue(directoryPath);
} else {
// 点击的是文件时
fileDataShow.value = true;
getFileData(directoryPath);
}
};
// 返回上一级
function backUpLevel() {
directoryPath = directoryPath.split("/").slice(0, -1).join("/");
getCatalogue(directoryPath);
if (directoryPath === "/Users/sanyuanui/Desktop/electronLocal") {
isShow.value = false;
}
}
// 获取文件信息
async function getFileData(path: string) {
try {
// 通过fs的readFileSync访问传输进来的地址文件数据
const content = fs.readFileSync(path, { encoding: "utf-8" });
// 讲文件数据反显到视图上
fileContent.value = content;
} catch (error) {
console.error(error);
}
}
// 保存文件内容
function saveFile() {
try {
fs.writeFileSync(directoryPath, fileContent.value, { encoding: "utf-8" });
fileDataShow.value = false;
directoryPath = directoryPath.split("/").slice(0, -1).join("/");
console.log("文件保存成功!");
} catch (error) {
console.error(error);
}
}
</script>
<style lang="less" scoped>
.box {
width: 100%;
height: 100%;
}
.logue-content {
display: inline-block;
width: 150px;
height: 120px;
img {
width: 50px;
height: 50px;
}
}
</style>