#前端本地文件操作与上传
前端无法像原生一样操作文件,否则打开网页就能把用户的东西偷光,所以只能通过以下三种方式触发:
- 通过input的file选择本地文件
- 通过拖拽方式把文件拖过来
- 在编辑框里面复制粘贴
<body>
<form action="" id="file-up">
<input type="file" name="file">
</form>
</body>
<script>
var form = document.forms.namedItem("file-up")
form["file"].onchange = function(){
console.log(`file name is ${this.value}`) ///这里的路径是一个假的路径,也就是说浏览器无法获取文件真实存放的位置。
// console.log(this.form)
let formData = new FormData(this.form)
formData.append("fileName",this.value)
console.log(formData) ///这里的formData是个空的,无法查看、修改、删除里面的内容,只能append字段
}
</script>
formData无法得到文件的内容,而使用fileReader可以读取文件的内容。
form["file"].onchange = function(){
console.log(`file name is ${this.value}`)
// console.log(this.form)
let fileReader = new FileReader()
fileType = this.files[0].type;
fileReader.onload = function(){
if(/^image\/[jpg/jpeg/png/gif]/.test(fileType)){ ///web不是所有的图片都是可以用img标签展示出来通常是jpg/png/gif
// 读取结果在fileReader.result里面
let img = new Image()
img.src = this.result;
console.log(this.result) ///读取的结果base64数据
document.body.appendChild(img)
}
}
console.log(this.files[0]) //打印file对象 里面包含里文件大小、文件名、文件类型(这里判断文件类型会比判断文件名更准确)
let fileData = fileReader.readAsDataURL(this.files[0])
}
fileReader的读取方式
readAsArrayBuffer(file) 二进制读取(读取结果直接转成整数数组)
readAsBinaryString(file) 二进制字符串方式读取,结果是二进制内容的utf-8(已经被废弃)
readAsDataURL(file) 以base64形式读取(任何文件都能转成base64)
readAsText(file,encoding) 按字符读取文件内容,结果用字符串形式表示
abort() 终止文件读取操作
事件
onabort 当读取操作被中止时调用
onerror 当读取操作发生错误时调用
onload 当读取操作成功完成时调用
onloadend 当读取操作完成时调用,无论成功或失败
onloadstart 当读取操作开始时调用
onprogress 在读取数据过程中周期性调用
##拖拽方式的判断
form["file"].ondrop = function(event){
console.log(event)
event.preventDefault();
event.cancelBubble = true; ///一定要防止冒泡
let file = event.dataTransfer.files[0];
readImage(file)
}
function readImage(file){ // 只能读取blob数据
let fileReader = new FileReader(file)
fileReader.readAsDataURL(file)
fileReader.onload = function(){
// console.log(file.type)
if(/^image\/[jpeg|png|gif]/.test(file.type)){
// 读取结果在fileReader.result里面
let img = new Image()
img.src = this.result;
// console.log(this.result) ///base64的结果
document.body.appendChild(img)
}
}
}
//或者可以添加到formData
let formData = new FormData();
formData.append("fileName",file)
##粘贴的方式
通常在一个编辑框里操作,如把一个div的contenteditable设置为true ,代码如下:
var edit = document.getElementById("edit")
edit.onpaste = function(event){
console.log(event)
let file = event.clipboardData.files[0]
readImage(file)
//也可以通过另一种方式获取这个文件
var item = e.clipboardData.items[i];
var blob = item.getAsFile();
}
但是safari的粘贴不是通过event传递的,而是直接在输入框添加了一张照片,新建了一个img的标签,将img的src指向一个blob的本地数据
blob 是一种文件的存储格式(blob派生了file),它可以存储几乎任何格式的内容
///blob
var data = {hello:'blob'}
var blob = new Blob([JSON.stringify(data)],{type:'application/json'})
console.log(blob) ///Blob(16) {size: 16, type: "application/json"}
##base64 转 blob
///base64 => blob
function b642blob(b64,contentType,sliceSize){
contentType = contentType || '';
sliceSize = sliceSize || 512;
let byteCharacters = window.atob(b64); /// 把base64还原 btoa 是把内容转化为base64
let byteArrays = [];
for(let offset = 0; offset<byteCharacters.length ; offset++){
let slice = byteCharacters.slice(offset , offset + sliceSize);
let byteNumbers = new Array(slice.length);
for(let i = 0; i< slice.length; i++){
byteNumbers[i] = slice.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray)
}
var blob = new Blob(byteArrays,{type:contentType})
console.log(blob)
return blob;
}
##XMLHttpRequest 2.0 可以获取文件的上传进度
xhr.upload.onprogress = function(event){
if(event.lengthComputable){
// 当前上传的百分比
duringCallback((event.loaded/event.total)*100)
}
}
上传blob
//上传数据
$.ajax({
url: url,
type: 'post',
processData: false,
contentType: false,
data: formData,
dataType: 'json',
success: function (data) {
var obj = eval(data);
if (obj.responseCode == '0') {
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus + "---" + errorThrown);
}
});
input 调用相机/录视频
// 相机
<input type="file" accept="image/*" capture="camera">
// 视频
<input type="file" accept="video/*" capture="camcorder">
// 音频
<input type="file" accept="audio/*" capture="microphone">
capture表示,可以捕获到系统默认的设备,比如:camera--照相机;camcorder--摄像机;microphone--录音。
accept表示,直接打开系统文件目录。
input:file标签还支持一个multiple属性,表示可以支持多选