1.Blob
blob数据类型以随机存取块的形式存储任何种类的二进制数据;二进制数据通常由已保存的电子表格、程序装入模块和数字化声音模式等等组成,也就是说它通常用于存储大文件,通常用来读写文件,比如一个图片文件的内容就可以通过Blob 对象读写
在Web中,Blob类型的对象表示不可变的类似文件对象的原始数据,通俗点说,就是Blob对象是二进制数据,但它是类似文件对象的二进制数据,因此可以像操作File对象一样操作Blob对象,实际上,File继承自Blob(文件对象)。
构造函数
array 是一个由
ArrayBuffer
,ArrayBufferView
,Blob
,DOMString
等对象构成的Array
,或者其他类似对象的混合体,它将会被放进Blob
。DOMStrings 会被编码为 UTF-8。options(可选)
它可能会指定如下两个属性:
type
,默认值为""
,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。endings
,默认值为"transparent"
,用于指定包含行结束符\n
的字符串如何被写入。它是以下两个值中的一个:"native"
,代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者"transparent"
,代表会保持 blob 中保存的结束符不变 非标准
let blob = new Blob([typedArray.buffer], {type: 'application/octet-stream'}); // 传入一个合适的 MIME 类型
let blob2 = new Blob(["image/jpeg"],{type:"application/json"})
使用字符串构造一个blob对象
var debug = {hello: "world"};
var blob = new Blob([JSON.stringify(debug)], {type : 'application/json'});
- 第一个参数是数组,数组元素可以是字符串或二进制文件,用来表示Blob实例对象的数据内容。
- 第二个参数是配置对象,但是目前该对象只有一个type属性可提供配置,它的值是一个字符串,表示数据的MIME类型,默认是空字符串,关于MIME类型分类,可以参照以下这张表:
blob2url
此时前端可以将Blob数据转换为url下载地址
export function downBlob(blobData: Blob, fileName: string) {
// 下载地址
const downUrl = window.URL.createObjectURL(blobData);
const a = document.createElement('a');
a.style.display = 'none';
a.href = downUrl;
a.target = '_blank';
if (fileName) {
a.download = fileName;
}
document.body.appendChild(a);
a.click();
a.remove();
window.URL.revokeObjectURL(downUrl); // 释放掉blob对象
}
url2blob
对于canvas生成的base64 url,也就是Data URL 格式的图片数据,为了进一步减少传输的数据量,我们可以把它转换为 Blob 对象,再传给服务端
function dataUrlToBlob(base64, mimeType) {
let bytes = window.atob(base64.split(",")[1]);
let ab = new ArrayBuffer(bytes.length);
let ia = new Uint8Array(ab);
for (let i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
return new Blob([ab], { type: mimeType });
}
URL.createObjectURL
URL.createObjectURL()
静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
- createObjectURL返回一段带hash的url,并且一直存储在内存中,直到document触发了unload事件(例如:document close)或者执行revokeObjectURL来释放。
File
文件(File
)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
通常情况下, File
对象是来自用户在一个 input 元素上选择文件后返回的 FileList
对象,也可以是来自由拖放操作生成的 DataTransfer
对象,或者来自 HTMLCanvasElement
上的 mozGetAsFile
() API。
File
对象是特殊类型的 Blob
,且可以用在任意的 Blob 类型的 context 中。
File()
FormData
FormData
接口提供了一种表示表单数据的键值对 key/value
的构造方式,并且可以轻松的将数据通过XMLHttpRequest.send()
方法发送出去,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 "multipart/form-data"
,它会使用和表单一样的格式。
它的用法和 map 有点像
构造函数
-
创建一个新的
FormData
对象。
方法
-
向
FormData
中添加新的属性值,FormData
对应的属性值存在也不会覆盖原值,而是新增一个值,如果属性不存在则新增一项属性值。 -
从 FormData 对象里面删除一个键值对。
-
返回一个包含所有键值对的
iterator
对象。 -
返回在 FormData
对象中与给定键关联的第一个值。 -
返回一个包含
FormData
对象中与给定键关联的所有值的数组。 -
返回一个布尔值表明 FormData
对象是否包含某些键。 -
返回一个包含所有键的
iterator
对象。 -
给
FormData
设置属性值,如果FormData
对应的属性值存在则覆盖原值,否则新增一项属性值。 -
返回一个包含所有值的
iterator
对象。
2.选择图片上传
在元素方面,我们可以选择 input
<input type="file" />
<input type="file" accept="image/*">
<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" multiple />
通过设置其 multiple
属性和 accept
属性可以使得 input
标签支持多选和仅支持选择 gif
、jpg/jpeg
和 png
类型的文件
然后可以对input读取到的数据,采用
2种方式
URL.createObjectURL(file)
,得到图片的url,由于可以获取到每张图片的File
对象,则可以使用URL.createObjectURL()
创建一个对象 URL,可以作为img
标签的src
值进行传入,则能实现本地图片的预览功能。需要注意的是,当不再需要这些使用
URL.createObjectURL()
创建的 URL 对象时,每个对象必须通过调用URL.revokeObjectURL()
方法来释放const localUrl = URL.createObjectURL(flieList[0]) // localUrl 可作为图片的源 <img src={localUrl} alt='' /> // 无需使用时释放内存 window.URL.revokeObjectURL(localUrl);
创建一个FileReader对象,监听它的load事件
$inputFile.addEventListener('change', function() { const file = this.files[0]; const reader = new FileReader(); reader.addEventListener('load', function() { $previewImage.src = reader.result; }, false); if(file) { reader.readAsDataURL(file); } }
上传
前端要实现图片上传的原理就是通过构建FormData
对象,把文件对象append()
到该对象,然后挂载在XMLHttpRequest
对象上 send()
到服务端。(如果是得到本地url可以通过
fetch(data.url).then((resp) => {
console.log(resp);
return resp.blob();
}).then((b) => {
console.log('---- bb', b);
const fd = new FormData();
fd.append('file', b);
console.log(fd, 'fd');
});
得到blob数据格式)
function uploadFile() {
//这里是用cropperjs对图片进行裁剪
cropperInstance.getCroppedCanvas().toBlob(function(blob) {
const formData = new FormData();
formData.append('avatar', blob);
fetch('xxxx', {
method: 'POST',
body: formData
});
});
}
3.文件上传
文件上传实质上和图片上传差不多,都是使用input获取文件
<div>
<input
onChange={(v)=>this.handleChange(v)}
type="file"
size={this.state.size}
name="fileSelect"
accept="image/*"
multiple={this.state.multiple} />
<span ref="dragBox"
onDragOver={(e)=>this.handleDragHover(e)}
onDragLeave={(e)=>this.handleDragHover(e)}
onDrop={(e)=>this.handleDrop(e)}
className="upload-drag-area">
或者将图片拖到此处
</span>
</div>
处理图片上传的函数handleChange
e.preventDefault()
let target = event.target
let files = target.files
let count = this.state.multiple ? files.length : 1
for (let i = 0; i < count; i++) {
files[i].thumb = URL.createObjectURL(files[i])
}
// 转换为真正的数组
files = Array.prototype.slice.call(files, 0)
// 过滤非图片类型的文件
files = files.filter(function (file) {
return /image/i.test(file.type)
})
处理拖拽进来的文件:
handleDrop(e) {
this.setState({progress:[]})
this.handleDragHover(e)
// 获取文件列表对象
let files = e.target.files || e.dataTransfer.files
let count = this.state.multiple ? files.length : 1
for (let i = 0; i < count; i++) {
files[i].thumb = URL.createObjectURL(files[i])
}
// 转换为真正的数组
files = Array.prototype.slice.call(files, 0)
// 过滤非图片类型的文件
files = files.filter(function (file) {
return /image/i.test(file.type)
})
this.setState({files: this.state.files.concat(files)})
}
上传函数
upload(file, idx) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
if (xhr.upload) {
// 上传中
xhr.upload.addEventListener("progress", (e) => {
// 处理上传进度
this.handleProgress(file, e.loaded, e.total, idx);
}, false)
// 文件上传成功或是失败
xhr.onreadystatechange = (e) => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// 上传成功操作
this.handleSuccess(file, xhr.responseText)
// 把该文件从上传队列中删除
this.handleDeleteFile(file)
resolve(xhr.responseText);
} else {
// 上传出错处理
this.handleFailure(file, xhr.responseText)
reject(xhr.responseText);
}
}
}
// 开始上传
xhr.open("POST", this.state.uri, true)
let form = new FormData()
form.append("filedata", file)
xhr.send(form)
})
}
只是上看了好多篇文章,他们对于上传图片的请求好多都是直接用原生xhr来写,而且原声xhr也有自带的上传终止功能(abort)
修改请求头
在上传的时候如果请求的数据格式有点问题,可以调整一下请求头再发请求,比如:
let config = {
headers:{'Content-Type':'multipart/form-data'}
}; //添加请求头
this.axios.post('http://upload.qiniu.com/',param,config)
.then(response=>{
console.log(response.data);
})
参考: