關(guān)于input type="file"的及其files對(duì)象的深度解析
我們都知道,html5中有個(gè)input type=file元素。用該元素可以實(shí)現(xiàn)頁面上傳文件的功能
但一般的做法只是簡(jiǎn)單的在表單中操作,我來研究一下深層?xùn)|西
想要了解它,就要知道它的內(nèi)置對(duì)象,files
頁面上寫一個(gè)input,然后選倆個(gè)圖片,打印這個(gè)input對(duì)象
$("input[name='file1']").change( function(e){
console.log($("input[name='file1']"))
})發(fā)現(xiàn)有下列值,在0中,有一個(gè)files對(duì)象


我們發(fā)現(xiàn)input選擇的文件被記錄到了這個(gè)對(duì)象中,這個(gè)是fileList對(duì)象,是一個(gè)只讀對(duì)象,不能修改
因?yàn)樗荒苄薷?,所以很難實(shí)現(xiàn)對(duì)已選中多個(gè)文件的刪除某個(gè)文件等操作
里面記錄了文件的name,size,type,和修改時(shí)間等,可知這個(gè)對(duì)象只存放了一些文件的信息,相當(dāng)于是本地文件的索引,并不是把文件放到input中了,上傳文件時(shí)它會(huì)再去找到實(shí)際的本地文件
fileList數(shù)組包含多個(gè)File對(duì)象,F(xiàn)ile對(duì)象是繼承與Blob對(duì)象的,關(guān)于file,url,blob,dataUrl可以詳細(xì)查查
一般url可以是本地地址,http地址等
blob對(duì)象一般的形式是:blob:http://192.168.100.151:8080/1148dcd6-952e-4478-823d-21b37e537c2f,屬于瀏覽器對(duì)象
dataUrl 一直格式是:以data:image/jpeg;base64,這種類似形式打頭的一串很長(zhǎng)的字符串。
這三種形式在img標(biāo)簽中src屬性都可以調(diào)用。
File對(duì)象有name,size,lastModified屬性
File對(duì)象的創(chuàng)建:
var file1=new File([blob], "aa.png",{type:"image/jpg"}); //第一個(gè)參數(shù)是Blob對(duì)象或者dataUrl,第二個(gè)參數(shù)是文件名,三個(gè)參數(shù)可選,規(guī)定文件類型
注意:第一個(gè)參數(shù)必須是對(duì)象,不能是轉(zhuǎn)換成的字符串,比如uniapp或者微信小程序的chooseImage方法返回的blob的url,他是一個(gè)字符串,這樣生成的File對(duì)象只是將url字符串變成文件了,不是文件本身?。?!
想把blob字符串變成Blob對(duì)象,可以用es6的:const blob = await fetch(image.path).then(r => r.blob())
或者用傳統(tǒng)的XHR或者ajax也行,就是把blob對(duì)象根據(jù)url給獲取出來就行。
利用這個(gè)files對(duì)象,我們可以實(shí)現(xiàn)很多功能,例如:
一.選擇圖片未經(jīng)后端顯示預(yù)覽圖片
方法1:利用window的url工具將文件生成url,再將url賦值給img的src屬性,顯示出選中圖像
順便提一下,input中控制選中類型加一個(gè)accept屬性就行了,只會(huì)顯示設(shè)定的文件類型
<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();
// 根據(jù)這個(gè) <input> 獲取文件的 HTML5 js 對(duì)象
var files = event.target.files, file;
if (files && files.length > 0) {
// 獲取目前上傳的文件
file = files[0];
// 來在控制臺(tái)看看到底這個(gè)對(duì)象是什么
console.log(file);
// 那么我們可以做一下諸如文件大小校驗(yàn)的動(dòng)作
if(file.size > 1024 * 1024 * 2) {
alert('圖片大小不能超過 2MB!');
return false;
}
// !!!!!!
// 下面是關(guān)鍵的關(guān)鍵,通過這個(gè) file 對(duì)象生成一個(gè)可用的圖像 URL
// 獲取 window 的 URL 工具
var URL = window.URL || window.webkitURL;
// 通過 file 生成目標(biāo) url
var imgURL = URL.createObjectURL(file);
// 用這個(gè) URL 產(chǎn)生一個(gè) <img> 將其顯示出來
$('.fbpj .container').prev().find("img").attr('src', imgURL);
// 使用下面這句可以在內(nèi)存中釋放對(duì)此 url 的伺服,跑了之后那個(gè) 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'); //默認(rèn)是用utf-8格式輸出的,想指定輸出格式就再添加一個(gè)參數(shù),像txt的ANSI格式只能用國(guó)標(biāo)才能顯示出來
}
}
</script>
</head>
<body>
<input type="file" id="file" onchange="handleFiles(this.files)"/>
<div id="filecontent"></div>
</body>
</html> readAsText一般只能讀取txt,html等等文件,局限性較大,比如想要前端讀excel文件,由于解決文件編碼問題較為復(fù)雜,需要用到j(luò)s-xlsx插件,具體可百度方法。
常用API:
FileReader.readAsDataURL(File) //轉(zhuǎn)換成base64格式
FileReader.readAsText() //轉(zhuǎn)換成字符串格式
FileReader.readAsArrayBuffer(File) //轉(zhuǎn)換成ArrayBuffer格式
FileReader.readAsBinaryString(File) //轉(zhuǎn)換成原始二進(jìn)制格式(貌似已被廢除)
FileReader.onload = function (e) { console.log(e.target.result) } //在上述讀取事件完成時(shí)觸發(fā)
二.文件拖拽的方法保存文件
關(guān)于文件拖拽下面有注釋,我主要說一下怎么給用js給input賦值,而不是手動(dòng)去選文件
因?yàn)橥献У膮^(qū)域只是一個(gè)div,無法進(jìn)行上傳操作,所以需要加一個(gè)form和input,讓拖拽進(jìn)去的文件進(jìn)入input中。
取出files后,用$("#file1")[0].files=files;將文件賦值給input,注意賦值的必須是fileList對(duì)象,不要試圖只放進(jìn)去一個(gè)文件,fileList只讀。
然后用h5中的FormData將form轉(zhuǎn)化,提交即可
<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>
培訓(xùn)活動(dòng)列表
</title>
</head>
<body>
<div class="container">
拖拽進(jìn)入
</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; //關(guān)鍵:將取到的文件賦值給input,用于ajax提交文件?。?!
var formData = new FormData($("#form1")[0]);
$.ajax({
url : "/it/orderManage/saveActivity",
type : 'POST',
data : formData,
// 告訴jQuery不要去處理發(fā)送的數(shù)據(jù)
processData : false,
// 告訴jQuery不要去設(shè)置Content-Type請(qǐng)求頭
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){ //不好判斷是否是文件夾,通過上傳報(bào)錯(cuò)可以判斷是文件夾
callback(false,file);
}
return true;
};
</script>
</body>
</html>后臺(tái)獲取文件還是用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()轉(zhuǎn)化一下。
所以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();
//添加表單參數(shù),如果后臺(tái)用文件數(shù)組接收
//param.append("file", e.target.files);
//如果后臺(tái)只接收單一文件
param.append("file", e.target.files[0]);
//設(shè)置表頭類型
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();
//文件可以在參數(shù)中用MultipartFile[](多文件) 或者 MultipartFile (單一文件)接收
//也可以像這樣在request中接收
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile multifile = multipartRequest.getFile("file"); // 通過參數(shù)名獲取指定文件
String fileName = multifile.getOriginalFilename();
// 獲取文件后綴
String prefix=fileName.substring(fileName.lastIndexOf("."));
// 用uuid作為文件名,防止生成的臨時(shí)文件重復(fù)
final File file = File.createTempFile(UUID.randomUUID().toString(), prefix);
// MultipartFile to File
return JSON.toJSONString(retBase, SerializerFeature.WriteMapNullValue);
}到此這篇關(guān)于關(guān)于input type="file"的及其files對(duì)象的深層探究的文章就介紹到這了,更多相關(guān)input type="file"內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
html5中去掉input type date默認(rèn)樣式的方法
這篇文章主要介紹了html5中去掉input type date默認(rèn)樣式的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-06
HTML5 input新增type屬性color顏色拾取器的實(shí)例代碼
type 屬性規(guī)定 input 元素的類型。本文較詳細(xì)的給大家介紹了HTML5 input新增type屬性color顏色拾取器的實(shí)例代碼,感興趣的朋友跟隨腳本之家小編一起看看吧2018-08-27HTML5中input[type='date']自定義樣式與日歷校驗(yàn)功能的實(shí)現(xiàn)代碼
HTML5提供了日歷控件功能,縮減了開發(fā)時(shí)間,但是有些地方也不是很好,下面給大家分享一段代碼片段關(guān)于HTML5中input[type='date']自定義樣式與日歷校驗(yàn)功能,需要的的朋友參2017-07-11


