关于input type=“file”的及其files对象的深层探究

关于input type=“file”的及其files对象的深层探究我们都知道,html5中有个inputtype=file元素。用该元素可以实现页面上传文件的功能但一般的做法只是简单的在表单中操作,我来研究一下深层东西想要了解它,就要知道它的内置对象,files页面上写一个input,然后选俩个图片,打印这个input对象$(“input[name=’file1′]”).change(function(e){console.log…

大家好,又见面了,我是你们的朋友全栈君。

我们都知道,html5中有个input type=file元素。用该元素可以实现页面上传文件的功能

但一般的做法只是简单的在表单中操作,我来研究一下深层东西

想要了解它,就要知道它的内置对象,files

页面上写一个input,然后选俩个图片,打印这个input对象

$("input[name='file1']").change( function(e){
    console.log($("input[name='file1']"))
})

发现有下列值,在0中,有一个files对象

关于input type=“file”的及其files对象的深层探究

关于input type=“file”的及其files对象的深层探究

我们发现input选择的文件被记录到了这个对象中,这个是fileList对象,是一个只读对象,不能修改

因为它不能修改,所以很难实现对已选中多个文件的删除某个文件等操作

里面记录了文件的name,size,type,和修改时间等,可知这个对象只存放了一些文件的信息,相当于是本地文件的索引,并不是把文件放到input中了,上传文件时它会再去找到实际的本地文件

fileList数组包含多个File对象,File对象是继承与Blob对象的,关于file,url,blob,dataUrl可以详细查查

一般url可以是本地地址,http地址等

blob对象一般的形式是:blob:http://192.168.100.151:8080/1148dcd6-952e-4478-823d-21b37e537c2f,属于浏览器对象

dataUrl 一直格式是:以data:image/jpeg;base64,这种类似形式打头的一串很长的字符串。

这三种形式在img标签中src属性都可以调用。

File对象有name,size,lastModified属性

File对象的创建:

var file1=new File([blob], “aa.png”,{type:”image/jpg”}); //第一个参数是Blob对象或者dataUrl,第二个参数是文件名,三个参数可选,规定文件类型

注意:第一个参数必须是对象,不能是转换成的字符串,比如uniapp或者微信小程序的chooseImage方法返回的blob的url,他是一个字符串,这样生成的File对象只是将url字符串变成文件了,不是文件本身!!!

想把blob字符串变成Blob对象,可以用es6的:const blob = await fetch(image.path).then(r => r.blob())

或者用传统的XHR或者ajax也行,就是把blob对象根据url给获取出来就行。

利用这个files对象,我们可以实现很多功能,例如:

一.选择图片未经后端显示预览图片

方法1:利用window的url工具将文件生成url,再将url赋值给img的src属性,显示出选中图像

顺便提一下,input中控制选中类型加一个accept属性就行了,只会显示设定的文件类型

<input id="file1" type="file"  name="file1" multiple="multiple" accept=".doc,.jpg">
$('.fbpj-camera').change(function(event) {
	 	//$('.dianpuzhuangxiu .addmokuai .block .shuoming1 .pic .pic1').children().remove();
   		 // 根据这个 <input> 获取文件的 HTML5 js 对象
	    var files = event.target.files, file;        
	    if (files && files.length > 0) {
	      // 获取目前上传的文件
	      file = files[0];
	      // 来在控制台看看到底这个对象是什么
	      console.log(file);
	      // 那么我们可以做一下诸如文件大小校验的动作
	      if(file.size > 1024 * 1024 * 2) {
	        alert('图片大小不能超过 2MB!');
	        return false;
	      }
	      // !!!!!!
	      // 下面是关键的关键,通过这个 file 对象生成一个可用的图像 URL
	      // 获取 window 的 URL 工具     
	      var URL = window.URL || window.webkitURL;     
	      // 通过 file 生成目标 url
	      var imgURL = URL.createObjectURL(file);
	      // 用这个 URL 产生一个 <img> 将其显示出来
	      $('.fbpj .container').prev().find("img").attr('src', imgURL);
	      // 使用下面这句可以在内存中释放对此 url 的伺服,跑了之后那个 URL 就无效了
	      	 //URL.revokeObjectURL(imgURL);
   		 }
  		});

方法二:利用html5的FileReader()读取文件

*前提是浏览器支持的话

if(window.FileReader) {  
    var fr = new FileReader();  
    // add your code here  
}  
else {  
    alert("Not supported by your browser!");  
} 
<script type="text/javascript">  
        function showPreview(source) {  
            var file = source.files[0];  
            if(window.FileReader) {  
                var fr = new FileReader();  
                fr.onloadend = function(e) {  
                    document.getElementById("portrait").src = e.target.result;  
                };  
                fr.readAsDataURL(file);  //也是利用将图片作为url读出
            }  
        }  
    </script>  
  
<input type="file" name="file" onchange="showPreview(this)" />  
                                <img id="portrait" src="" width="70" height="75">  

FileReader还有一些其他用法

<html>  
  <head>  
  <meta http-equiv="content-type" content="text/html; charset=utf-8">  
  <meta name="author" content="oscar999">  
  <title></title>  
  <script>  
  function  handleFiles(files)  
  {  
    if(files.length)  
    {  
       var file = files[0];  
       var reader = new FileReader();  
       reader.onload = function()  
       {  
           document.getElementById("filecontent").innerHTML = this.result;  
       };  
       reader.readAsText(file);   //作为字符串读出
        //reader.readAsText(file,'gb2312');   //默认是用utf-8格式输出的,想指定输出格式就再添加一个参数,像txt的ANSI格式只能用国标才能显示出来
    }  
  }  
  </script>  
    
  </head>  
  <body>  
  
  <input type="file" id="file" onchange="handleFiles(this.files)"/>  
  <div id="filecontent"></div>  
  </body>  
</html>  

readAsText一般只能读取txt,html等等文件,局限性较大,比如想要前端读excel文件,由于解决文件编码问题较为复杂,需要用到js-xlsx插件,具体可百度方法。

常用API:

FileReader.readAsDataURL(File) //转换成base64格式

FileReader.readAsText() //转换成字符串格式

FileReader.readAsArrayBuffer(File) //转换成ArrayBuffer格式

FileReader.readAsBinaryString(File) //转换成原始二进制格式(貌似已被废除)

FileReader.onload = function (e) { console.log(e.target.result) } //在上述读取事件完成时触发

二.文件拖拽的方法保存文件

关于文件拖拽下面有注释,我主要说一下怎么给用js给input赋值,而不是手动去选文件

因为拖拽的区域只是一个div,无法进行上传操作,所以需要加一个form和input,让拖拽进去的文件进入input中。

取出files后,用$(“#file1”)[0].files=files;将文件赋值给input,注意赋值的必须是fileList对象,不要试图只放进去一个文件,fileList只读。

然后用h5中的FormData将form转化,提交即可

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <style>
        .container{
            width:300px;height: 300px;
            border:2px dashed #ddd;
            text-align: center;
            padding:50px;
        }
    </style>
    <title>
        培训活动列表
    </title>
</head>
<body>
<div class="container">
    拖拽进入
</div>
<form id="form1" method="post" enctype="multipart/form-data">
    <input type="file" name="file1" id="file1" value="" />
</form>
<script type="text/javascript">
    $('.container').bind('dragenter dragover', ignoreDrag);
    $(".container").on({drop:function(e){
        var flag=true;
        e.preventDefault();
        //jquery的file要去e.originalEvent里面拿,拖拽获取files的方式与input的不同
        var files = e.originalEvent.dataTransfer.files;
        //var files = e.dataTransfer.files;  原生的话这样就可以获取
        for(var i=0;i<files.length;i++){
            myFileReader(files[i],function(result,file){
                if(result){
                    //文件
                    console.log(file.name)

                }else{
                    //文件夹
                    console.log("不要上传文件夹")
                    flag=false;
                }
            });
        }
        if(flag){
            $("#file1")[0].files=files;   //关键:将取到的文件赋值给input,用于ajax提交文件!!!
            var formData = new FormData($("#form1")[0]);     
            $.ajax({
                url : "/it/orderManage/saveActivity",
                type : 'POST',
                data : formData,
                // 告诉jQuery不要去处理发送的数据
                processData : false,
                // 告诉jQuery不要去设置Content-Type请求头
                contentType : false,
                async : true,
                success : function(ret) {
                    //alert("上传成功")
                    if(ret){
                        $("#trainInfoModal").modal("hide");
                        layer.alert("保存成功")
                        $('#orderTable').bootstrapTable("refresh");
                        $("#trainInfoModal input").val("");
                        $("#trainInfoModal textarea").val("");

                    }
                }
            });
        }
        console.log(files);
    }})

    function ignoreDrag(e) {e.originalEvent.stopPropagation();
        e.originalEvent.preventDefault();
    }

    function myFileReader(file, callback){
        if(!window.FileReader){
            callback(true,file);
            return false;
        }
        var fr = new FileReader();
        fr.readAsDataURL(file);
        fr.onload=function(e){
            callback(true,file);
        }
        fr.onerror=function(e){  //不好判断是否是文件夹,通过上传报错可以判断是文件夹
            callback(false,file);
        }
        return true;
    };
</script>
</body>
</html>

后台获取文件还是用MutipartFile[]接收

public String saveActivity(@RequestParam HashMap<String, String> param,
                               //@RequestParam(value = "banner") MultipartFile[] files,
                               @RequestParam(value = "file1") MultipartFile[] file1,
                               HttpServletRequest request,
                               String fileNames,
                               String TID, HttpServletRequest req) {
  
  

三.vue+axios 上传文件

无论ajax还是axios,都不是直接用表单提交的,都是 要用 new FormData()转化一下。

所以axios方法与ajax方法类似

<input type="file" class="inputBtn"  @change="uploadMarketingForm">
uploadMarketingForm(e){
	console.log(e)
	var fileName=e.target.files[0].name; //文件名
	var fileSize=e.target.files[0].size; //文件大小
	var param = new FormData();
        //添加表单参数,如果后台用文件数组接收
        //param.append("file", e.target.files);
        //如果后台只接收单一文件
	param.append("file", e.target.files[0]);
        //设置表头类型
	const config = {
		headers: { "Content-Type": "multipart/form-data" }
	};
	this.axios.post("/.../uploadTest", param, config).then(res => {
		console.log(res);
	});
},

在java spring mvc中还是这么接收

@ResponseBody
@RequestMapping(value = "uploadTest", produces = "text/plain;charset=UTF-8")
public String uploadTest(@RequestParam Map<String,String> param,@RequestParam(value = "file") MultipartFile[] file1,
                         HttpServletRequest request) throws IOException {
    RetBase retBase = new RetBase();
    //文件可以在参数中用MultipartFile[](多文件) 或者 MultipartFile (单一文件)接收
    //也可以像这样在request中接收
    MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
    MultipartFile multifile = multipartRequest.getFile("file"); // 通过参数名获取指定文件
    String fileName = multifile.getOriginalFilename();
    // 获取文件后缀
    String prefix=fileName.substring(fileName.lastIndexOf("."));
    // 用uuid作为文件名,防止生成的临时文件重复
    final File file = File.createTempFile(UUID.randomUUID().toString(), prefix);
    // MultipartFile to File
    return JSON.toJSONString(retBase, SerializerFeature.WriteMapNullValue);
}

 云服务器ESC购买地址:云服务器ECS_云主机_服务器托管_弹性计算-阿里云

对象存储oss购买地址:对象存储OSS_云存储服务_企业数据管理_存储-阿里云

SSL证书购买地址:证书服务_SSL数字证书_HTTPS加密_服务器证书_CA认证-阿里云

CDN云产品购买地址 :CDN_内容分发网络_CDN网站加速-阿里云

 

关于input type=“file”的及其files对象的深层探究

关于input type=“file”的及其files对象的深层探究

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/131733.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号