JavaScript如何获取用户input[type=file]选择的文件路径呢?

首先,JavaScript本身是无法通过input[type=file]获取用户选择的文件路径的,这条路是行不通的。

  • 有经验的都知道,这样获取到的路径是 C:/fakepath/...一类的路径。

所以,那我们还有办法通过input[type=file]获取文件的路径吗?

答案:

  1. 写一个C++去调用系统底层的一些东西,然后交给JavaScript调用这个C++文件
  2. 曲线救国

C++,我…不会写,所以还是看一下曲线救国


注意:得用node,不过现在vue,react,angualr项目,使用个node想必没得问题。


OK,我们继续:

首先,分开看问题:

  • 我们要获取文件的绝对路径。
  • 获取的文件是用户通过input[type=file]选择的文件。

这两者有关系吗?有,好像又没有:

  • 有:我们需要获取的是用户选择的文件的路径
  • 没有:我们需要获取的是一个文件路径,路径地址指向的文件和用户选择的文件一模一样。

所以,如果用户选择的文件,在某个我们的 项目代码 能 访问到的地址 里 有个备份 是不是就完美解决了这个问题

  • 能访问到的地址:那肯定是你的项目目录了,这样你的代码都能访问到。
    • 还能用nodepath.resolve()获取到程序所在的绝对路径目录或者将相对目录解析成绝对目录。
  • 备份:那就是文件拷贝了。

文件拷贝好像是个麻烦事,而且曲线救国的曲线,也主要是在这里,大致分为以下几步:

  1. 首先在项目根目录创建一个temp临时文件夹【不用创建也行,写入文件时会自动创建】
  2. 获取用户通过input[type=file]选择的文件的file对象,如果是多选,获取的就是一个file对象数组.
  3. 通过FileReaderfile对象,转换为一个buffer
  4. 利用node的文件写入方法,将buffer写入到我们创建出来的文件中。【这一步不明白的我后面会有解释】

文件拷贝:代码简述

  • 获取用户选择的文件的file对象:

    <input type="file" name="copy" id="copy" multiple>
    
    // 这里强调一下:框架有框架自己的获取dom元素的方法,而且input[type=file]的change事件,在框架中其实也用不着获取dom元素,直接把input标签上绑定事件就好了。
    // 这里最主要的就是获取到file对象,我这么写,只是为了做一下演示
    let fileBtn = document.getElementById('copy');
    fileBtn.addEventListener('change', (file) => {
    	let filesArr = file.target.files;
    	console.log(filesArr);
    });
    
  • 通过FileReader转换

    ...
    fileBtn.addEventListener('change', (file) => {
    	let filesArr = file.target.files;
    	
        for(let i = 0; i < filesArr.length; i++) {
            let fileReader = new FileReader();
            
            fileReader.onload = () => {
                // 这里输出出来的就是 buffer 对象
                console.log(fileReader.result);
            }
            
            fileReader.readAsArrayBuffer(filesArr[i]);
        }
        
    });
    
  • buffer写入到文件中。

    • 这一步 node 的操作是这样,虽然我们只是简单调用了一个方法,我简单说一下:
    1. 创建一个空的同名文件,在我们提供的文件位置下。
    2. 将buffer写入到这个文件中。

    有兴趣的可以去研究一下node怎么干的。

    import {writeFileSync} from "fs";
    ...
    fileReader.onload = () => {
        // 通过path.resolve,将temp文件夹解析成一个绝对地址,然后拼上文件名称
        writeFileSync(`${path.resolve(__dirname,'./src/temp')}/${filesArr[i].name}`, fileReader.result, (err)=>{
            if(err){
                console.log('文件写入失败');
                return;
            }
            console.log('文件写入成功');
        });
    }
    

    writeFileSyncnode文件系统中的一个文件写入的同步方法,可以将buffer数据,写入到文件文件中。

    这个函数接受几个参数,其中主要的:

    1. 文件名称,也可以是文件地址【若为文件地址,则其会为我们自动创建文件夹路径】
    2. buffer对象
    3. 回调函数

    具体了解,可以看菜鸟教程的讲解,我觉得挺好的,传送门:writeFileSync方法


其实到这里,就基本可以了,简单总结一下就是:将用户选择的文件,转化到我们的项目下,因为项目下的文件可以获取其绝对地址。

至于之后,要做什么操作,操作完了,是不是要删除掉,这都看需求啦。

而且,node对文件的操作很牛,删除什么的完全不是事。


PS: 看到了下面用户的评论,这里简单说一下:

  • 首先呢,这篇【曲线救国】的文章也只是我在在对js选择本地用户文件上的一个想法。
  • 其次,浏览器端到不是真的用不了nodejs,比如使用bowserify进行转化。我也是看到了这点,才写了这篇文章,但具体操作,还是要个人去实践才行,若你有成功的案例,欢迎回评!
  • 最后,其实想想,若你真的到了需要在浏览器中使用nodejs操作本地用户文件的地步,那说不得你的需求或逻辑出了这样或那样的问题😂,因为对用户来说这是极其不安全
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐