切换至深色主题
文件(File)实现技术
重要通知
类目简介
基本概况
文件格式
云点播支持上传以下类型的媒体文件: 视频:WMV、RM、MOV、MPEG、MP4、3GP、FLV、AVI、RMVB、TS、ASF、MPG、WEBM、MKV 、M3U8、WM、ASX、RAM、MPE、VOB、DAT、MP4V、M4V、F4V、MXF、QT、OGG。 音频:MP3、M4A、FLAC、OGG、WAV、RA、AAC、AMR。 图片:JPG、JPEG、PNG、GIF、BMP、TIFF、AI、CDR、EPS、TIF、HEIF。
上传文件案例
前台文件
<button type="button" id="uploadFile">上传文件</button>
<script type="text/javascript">
function getFileDataUtil(file) {
return new Promise((resolve) => {
file.onchange = async function (e) {
resolve(e.target.files[0]);
};
});
}
// fetch上传
async function uploadFileByFetch(formData) {
const result = await fetchAPI({
path: "https://api.ysunlight.com/api/upload/file-single?label=1&name=eshen",
method: "post",
data: formData,
uploadType: "file",
})
.then((res) => res)
.catch((err) => err);
console.info("上传文件:", result);
}
</script>
<script type="text/javascript">
var uploadFileEl = document.querySelector("#uploadFile");
uploadFileEl.onclick = async function () {
const file = document.createElement("input");
file.setAttribute("type", "file");
file.click();
const fileData = await getFileDataUtil(file);
console.info("File对象", fileData);
const formData = new FormData();
formData.append("file", fileData);
uploadFileByFetch(formData);
fetch("https://api.ysunlight.com/api/get")
.then((res) => {
console.log("上传成功: ", res);
})
.catch((err) => null);
// 原生方法
fetch("https://api.ysunlight.com/api/upload/file-single?name=eshen", {
method: "POST",
body: formData,
})
.then((res) => {
console.log("上传成功: ", res);
})
.catch((err) => null);
};
</script>后台文件
const fs = require("fs");
// https://api.ysunlight.com/api/upload/file-single
router.post("/api/upload/file-single", koaBody({
multipart: true,
encoding: 'gzip',
formidable: {
multipart: true,
keepExtensions: true,
maxFileSize: 10 * 1024 * 1024 * 1024 //10G
}
}), async (ctx) => {
let resdt = { status: 200, msg: "success", data: {} };
const query = ctx.request.query;
const method = ctx.request.method;
const header = ctx.request.header;
const url = ctx.request.url;
const body = ctx.request.body;
console.log("query: ", query);
console.log("method: ", method);
console.log("header: ", header);
console.log("url: ", url);
console.log("body: ", body);
// 接收文件
const fileData = ctx.request.files?.file || {};
console.log("fileData: ", fileData);
console.log("fileName: ", fileData?.originalFilename);
console.log("mimetype: ", fileData?.mimetype);
console.log("size: ", fileData?.size);
resdt.data['fileurl'] = await saveFile(fileData);
ctx.body = resdt;
process.stdout.write(`${JSON.stringify(resdt)}\n\n`);
});上传文件
<button type="button">上传文件</button>
<script type="text/javascript">
const button = document.querySelector("button");
button.addEventListener("click", uploadAction, false);
async function uploadAction() {
const fileEl = document.createElement("input");
if (!fileEl) return;
fileEl.setAttribute("type", "file");
fileEl.setAttribute("name", "input-file");
fileEl.setAttribute("multiple", "multiple");
fileEl.setAttribute("accept", "image/gif,image/jpeg,image/png");
fileEl.setAttribute("accept", ".doc,.docx,.xml,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document");
// accept不传,默认所有文件
// 任何音频文件
fileEl.setAttribute("accept", "audio/*");
// 任何视频文件
fileEl.setAttribute("accept", "video/*");
// 任何图片文件
fileEl.setAttribute("accept", "image/*");
fileEl.click();
const getFileData = (fileTarget) => {
return new Promise((resolve) => {
fileTarget.onchange = async function (e) {
resolve(e.target.files[0]);
};
});
};
const fileData = await getFileData(fileEl);
console.info("fileData: ", fileData);
const getReaderData = (fileData) => {
const reader = new FileReader();
reader.readAsDataURL(fileData); // 二进制
return new Promise((resolve) => {
reader.onload = function () {
resolve(reader.result);
};
});
};
const readerData = await getReaderData(fileData);
console.info("readerData: ", readerData);
}
</script>Content-Type 请求类型
# Content-Type 请求类型
multipart/form-data // FormData
application/x-www-urlencoded // 表单
application/json // json
application/json-patch+json
application/vnd.api+json
application/csp-report
text/xml
text/plain
# 包含类型 | application audio font example image message model multipart text video
/**
* MIME 类型
* MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准
* MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据
*
* Content-Type: 'image/png'
* Content-Length: data.length
*/
// 按照内容类型排列的 Mime 类型列表
-----------------------------------------------------------------
类型/子类型 扩展名
-----------------------------------------------------------------
text/html htm
text/html html
text/css css
text/javascript js
image/gif gif
image/jpeg jpeg
image/jpeg jpg
image/png png
application/pdf pdf
application/envoy evy
application/fractals fif
application/futuresplash spl
application/hta hta
application/internet-property-stream acx
application/mac-binhex40 hqx
application/msword doc
application/msword dot
application/octet-stream *
application/octet-stream bin
application/octet-stream class
application/octet-stream dms
application/octet-stream exe
application/octet-stream lha
application/octet-stream lzh
application/oda oda
application/olescript axs
application/pics-rules prf
application/pkcs10 p10
application/pkix-crl crl
application/postscript ai
application/postscript eps
application/postscript ps
application/rtf rtf
application/set-payment-initiation setpay
application/set-registration-initiation setreg
application/vnd.ms-excel xla
application/vnd.ms-excel xlc
application/vnd.ms-excel xlm
application/vnd.ms-excel xls
application/vnd.ms-excel xlt
application/vnd.ms-excel xlw
application/vnd.ms-outlook msg
application/vnd.ms-pkicertstore sst
application/vnd.ms-pkiseccat cat
application/vnd.ms-pkistl stl
application/vnd.ms-powerpoint pot
application/vnd.ms-powerpoint pps
application/vnd.ms-powerpoint ppt
application/vnd.ms-project mpp
application/vnd.ms-works wcm
application/vnd.ms-works wdb
application/vnd.ms-works wks
application/vnd.ms-works wps
application/winhlp hlp
application/x-bcpio bcpio
application/x-cdf cdf
application/x-compress z
application/x-compressed tgz
application/x-cpio cpio
application/x-csh csh
application/x-director dcr
application/x-director dir
application/x-director dxr
application/x-dvi dvi
application/x-gtar gtar
application/x-gzip gz
application/x-hdf hdf
application/x-internet-signup ins
application/x-internet-signup isp
application/x-iphone iii
application/x-javascript js
application/x-latex latex
application/x-msaccess mdb
application/x-mscardfile crd
application/x-msclip clp
application/x-msdownload dll
application/x-msmediaview m13
application/x-msmediaview m14
application/x-msmediaview mvb
application/x-msmetafile wmf
application/x-msmoney mny
application/x-mspublisher pub
application/x-msschedule scd
application/x-msterminal trm
application/x-mswrite wri
application/x-netcdf cdf
application/x-netcdf nc
application/x-perfmon pma
application/x-perfmon pmc
application/x-perfmon pml
application/x-perfmon pmr
application/x-perfmon pmw
application/x-pkcs12 p12
application/x-pkcs12 pfx
application/x-pkcs7-certificates p7b
application/x-pkcs7-certificates spc
application/x-pkcs7-certreqresp p7r
application/x-pkcs7-mime p7c
application/x-pkcs7-mime p7m
application/x-pkcs7-signature p7s
application/x-sh sh
application/x-shar shar
application/x-shockwave-flash swf
application/x-stuffit sit
application/x-sv4cpio sv4cpio
application/x-sv4crc sv4crc
application/x-tar tar
application/x-tcl tcl
application/x-tex tex
application/x-texinfo texi
application/x-texinfo texinfo
application/x-troff roff
application/x-troff t
application/x-troff tr
application/x-troff-man man
application/x-troff-me me
application/x-troff-ms ms
application/x-ustar ustar
application/x-wais-source src
application/x-x509-ca-cert cer
application/x-x509-ca-cert crt
application/x-x509-ca-cert der
application/ynd.ms-pkipko pko
application/zip zip
audio/basic au
audio/basic snd
audio/mid mid
audio/mid rmi
audio/mpeg mp3
audio/x-aiff aif
audio/x-aiff aifc
audio/x-aiff aiff
audio/x-mpegurl m3u
audio/x-pn-realaudio ra
audio/x-pn-realaudio ram
audio/x-wav wav
image/bmp bmp
image/cis-cod cod
image/ief ief
image/pipeg jfif
image/svg+xml svg
image/tiff tif
image/tiff tiff
image/x-cmu-raster ras
image/x-cmx cmx
image/x-icon ico
image/x-portable-anymap pnm
image/x-portable-bitmap pbm
image/x-portable-graymap pgm
image/x-portable-pixmap ppm
image/x-rgb rgb
image/x-xbitmap xbm
image/x-xpixmap xpm
image/x-xwindowdump xwd
message/rfc822 mht
message/rfc822 mhtml
message/rfc822 nws
text/h323 323
text/html stm
text/iuls uls
text/plain bas
text/plain c
text/plain h
text/plain txt
text/richtext rtx
text/scriptlet sct
text/tab-separated-values tsv
text/webviewhtml htt
text/x-component htc
text/x-setext etx
text/x-vcard vcf
video/mpeg mp2
video/mpeg mpa
video/mpeg mpe
video/mpeg mpeg
video/mpeg mpg
video/mpeg mpv2
video/quicktime mov
video/quicktime qt
video/x-la-asf lsf
video/x-la-asf lsx
video/x-ms-asf asf
video/x-ms-asf asr
video/x-ms-asf asx
video/x-msvideo avi
video/x-sgi-movie movie
x-world/x-vrml flr
x-world/x-vrml vrml
x-world/x-vrml wrl
x-world/x-vrml wrz
x-world/x-vrml xaf
x-world/x-vrml xof
-----------------------------------------------------------------ActiveXObject
该对象是微软的私有拓展名, 只在微软的IE浏览器上支持,ActiveXObject 启用会返回一个自动化对象的引用,这个对象只能用于实例化自动化对象,它没有任何成员对象。
# 语法
let newObj = new ActiveXObject(servername, typename[, location])
# 参数
> servername:提供对象的应用程序的名称
> typename: 要创建的对象的类型或类
> location: 要创建对象的网络服务器的名称
# 备注
> servername.typename的值:Excel.Application、Excel.Chart、Scripting.FileSystemObject、WScript.Shell、Word.Document;
# 兼容性支持
> Supported in the following document modes: Quirks, Internet Explorer 6 standards, Internet Explorer 7 standards, Internet Explorer 8 standards, Internet Explorer 9 standards, Internet Explorer 10 standards, Internet Explorer 11 standards.File对象
File对象数据结构
{
lastModified: 1713116761687
lastModifiedDate: Mon Apr 15 2024 01:46:01 GMT+0800 (中国标准时间) {}
name: "BB1lA8Hk.png"
size: 524776
type: "image/png"
webkitRelativePath: ""
}File 对象相关属性
File 对象是来自用户在一个
<input>元素上选择文件后返回的 FileList 对象 File 接口没有定义任何方法, 从 Blob 接口继承了以下方法, 也继承了 Blob 接口的属性
FileList
File
{
lastModified // 返回当前 File 对象所引用文件最后修改时间,自 UNIX 时间起始值(1970年1月1日 00:00:00 UTC)以来的毫秒数
lastModifiedDate // 返回当前 File 对象所引用文件最后修改时间的 Date 对象。
name // 返回当前 File 对象所引用文件的名字
size // 返回文件的大小
type // 返回文件的 多用途互联网邮件扩展类型(MIME Type)
webkitRelativePath // 返回 File 相关的 path 或 URL。
}
// 结构语法
const file = new File(
bits, // 一个包含ArrayBuffer,ArrayBufferView,Blob,或者 DOMString 对象的 Array — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。
name, // USVString,表示文件名称,或者文件路径。
options // 选项对象,包含文件的可选属性。type: DOMString,表示将要放到文件中的内容的 MIME 类型。默认值为 "" ,见WEB/AJAX/[Content-Type媒体类型与MIME 类型].md。lastModified: 数值,表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()。
);File 对象相关方法
Blob.slice
Blob.slice(
start: // 这个参数代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。
end: // 这个参数代表的是 Blob 的一个下标,这个下标-1的对应的字节将会是被拷贝进新的Blob 的最后一个字节。
contentType: // 给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。
);
const path = URL.createObjectURL(blob);
URL.revokeObjectURL(path);FileReader
FileReader
FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
FileReader属性
const reader = new FileReader();
reader.readyState
reader.result
// 异步
const getDataText = (content) => {
const reader = new FileReader();
reader.readAsText(content, 'utf-8');
return new Promise((resolve) => {
reader.onload = function() {
resolve(reader.result);
}
});
}
const dataText = await getDataText(textBlob);FileReader事件
const reader = new FileReader();
//解析文件开始
reader.onloadstart = function(e) {
console.log(e);
}
//解析文件进度
reader.onprogress = function(e) {
console.log(e);
}
//解析文件中断
reader.onabort = function(e) {
console.log(e);
}
//解析文件错误
reader.onerror = function(e) {
console.log(e);
}
//解析文件完成
reader.onload = function(e) {
const result = e.target.result || this.result;
console.log(e);
img.src = result;
//这样就获取到了文件的Base64字符串
//var base64 = getBase64Image(image);
//Base64字符串转二进制
//var file = dataURLtoBlob(base64);
//上传
var blob = new Blob([result], { type: 'image/jpg' });
var fd = new FormData();
fd.append('file', blob);
//提交到服务器, 见ajax
}
//解析文件结束
reader.onloadend = function(e) {
console.log(e);
}FileReader接口
const file = file.files[0];
const reader = new FileReader();
// 注意:需要在reader.onload中读取,因为内容才能保障解析完成
//读取为文本 readAsText(File|Blob [, encoding]) encoding:asni, utf-8, gbk2312, gb2312, binary
// reader.readAsText(file, 'gb2312');
//将文件读取为 二进制码 readAsBinaryString(File|Blob), 从 2012 年 7 月 12 日起,该方法已从 W3C 工作草案废除。
reader.readAsBinaryString(file);
//将文件读取为 DataURL readAsDataURL(File|Blob)
reader.readAsDataURL(file);
//将文件读取为 缓冲区 readAsArrayBuffer(File|Blob)
reader.readAsArrayBuffer(file);FileReaderSync
FileReaderSync接口允许以同步的方式读取File或Blob对象中的内容,该接口只在workers里可用,因为在主线程里进行同步I/O操作可能会阻塞用户界面。
https://developer.mozilla.org/zh-CN/docs/Web/API/FileReaderSync
基本类型 MIME-type
# -----------------------------------------------------------------------------------
文件后缀 MIME-type
# -----------------------------------------------------------------------------------
*.3gpp audio/3gpp, video/3gpp
*.ac3 audio/ac3
*.asf allpication/vnd.ms-asf
*.au audio/basic
*.css text/css
*.csv text/csv
*.doc application/msword
*.dot application/msword
*.dtd application/xml-dtd
*.dwg image/vnd.dwg
*.dxf image/vnd.dxf
*.gif image/gif
*.htm text/html
*.html text/html
*.jp2 image/jp2
*.jpe image/jpeg
*.jpeg image/jpeg
*.jpg image/jpeg
*.js text/javascript, application/javascript
*.json application/json
*.mp2 audio/mpeg, video/mpeg
*.mp3 audio/mpeg
*.mp4 audio/mp4, video/mp4
*.mpeg video/mpeg
*.mpg video/mpeg
*.mpp application/vnd.ms-project
*.ogg application/ogg, audio/ogg
*.pdf application/pdf
*.png image/png
*.pot application/vnd.ms-powerpoint
*.pps application/vnd.ms-powerpoint
*.ppt application/vnd.ms-powerpoint
*.rtf application/rtf, text/rtf
*.svf image/vnd.svf
*.tif image/tiff
*.tiff image/tiff
*.txt text/plain
*.wdb application/vnd.ms-works
*.wps application/vnd.ms-works
*.xhtml application/xhtml+xml
*.xlc application/vnd.ms-excel
*.xlm application/vnd.ms-excel
*.xls application/vnd.ms-excel
*.xlt application/vnd.ms-excel
*.xlw application/vnd.ms-excel
*.xml text/xml, application/xml
*.zip application/zip
*.xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
# -----------------------------------------------------------------------------------支持的文件类型
支持 doc, docx, xls, xlsx, xlsm, ppt, pptx, csv, tsv, dotm, xlt, xltm, dot, dotx,xlam, xla 等 Office 办公文档 支持 wps, dps, et, ett, wpt 等国产 WPS Office 办公文档 支持 odt, ods, ots, odp, otp, six, ott, fodt, fods 等OpenOffice、LibreOffice 办公文档 支持 vsd, vsdx 等 Visio 流程图文件 支持 wmf, emf 等 Windows 系统图像文件 支持 psd 等 Photoshop 软件模型文件 支持 pdf ,ofd, rtf 等文档 支持 xmind 软件模型文件 支持 bpmn 工作流文件 支持 eml 邮件文件 支持 epub 图书文档 支持 obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, dae, wrl, 3mf, ifc, brep, step, iges, fcstd, bim 等 3D 模型文件 支持 dwg, dxf 等 CAD 模型文件 支持 txt, xml(渲染), md(渲染), java, php, py, js, css 等所有纯文本 支持 zip, rar, jar, tar, gzip, 7z 等压缩包 支持 jpg, jpeg, png, gif, bmp, ico, jfif, webp 等图片预览(翻转,缩放,镜像) 支持 tif, tiff 图信息模型文件 支持 tga 图像格式文件 支持 svg 矢量图像格式文件 支持 mp3,wav,mp4,flv 等音视频格式文件 支持 avi,mov,rm,webm,ts,rm,mkv,mpeg,ogg,mpg,rmvb,wmv,3gp,ts,swf 等视频格式转码预览
二进制文件(.bin)
二进制文件,格式binary的缩写,例如main.bin。
数据结构之间转换
Blob转File对象
this.modal.data = URL.createObjectURL(data);
this.modal.visual = false;
// 转换函数
const file = new window.File([data], this.file.name)
let formData = new FormData();
formData.append("content", file);URL转Base64
URL转Blob
Base64转Blob
Blob转Base64
网络图像文件转Base64
function getBase64Image(img) {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, img.width, img.height);
var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
var dataURL = canvas.toDataURL("image/" + ext);
return dataURL;
};Base64字符串转二进制
见腾讯云COS上传示例。
function dataURItoBlobUtil(base64: string) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {
type: mime
});
};Base64字符串转二进制
dataURItoBlobUtil(dataURI) {
// base64 解码
let byteString = window.atob(dataURI.split(',')[1])
let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
let ab = new ArrayBuffer(byteString.length)
let ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ab], {type: mimeString})
}Blob | 使用 Blob 创建一个指向类型化数组的URL
后端返回blob数据:服务端返回的为资源的二进制数据 前端处理: 前端接收到二进制数据后,使用 URL.createObjectURL(blobData) 方法将服务端返回的二进制数据转换为 blob 的 url 资源挂载到相应的资源对象。
var typedArray = GetTheTypedArraySomehow();
var blob = new Blob([typedArray.buffer], {type: 'application/octet-stream'}); // 传入一个合适的 MIME 类型
var url = URL.createObjectURL(blob);利用canvas.toDataURL的API转化成base64
function base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
return new Promise((resolve, reject) => {
// 使用 atob() 方法将数据解码
let byteCharacters = atob(b64data);
let byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
let slice = byteCharacters.slice(offset, offset + sliceSize);
let byteNumbers = [];
for (let i = 0; i < slice.length; i++) {
byteNumbers.push(slice.charCodeAt(i));
}
// 8 位无符号整数值的类型化数组。内容将初始化为 0。
// 如果无法分配请求数目的字节,则将引发异常。
byteArrays.push(new Uint8Array(byteNumbers));
}
let result = new Blob(byteArrays, {
type: contentType
})
result = Object.assign(result,{
// 这里一定要处理一下 URL.createObjectURL
preview: URL.createObjectURL(result),
name: `XXX.png`
});
resolve(result)
})
}字符串与Blob转换
// 字符串转换为Blob
const text = "你好,我是字符串";
const textBlob = new Blob([text],{type: 'text/plain'});
console.info(textBlob);
// Blob转换为字符串
const getDataText = (content) => {
const reader = new FileReader();
reader.readAsText(content, 'utf-8');
return new Promise((resolve) => {
reader.onload = function() {
resolve(reader.result);
}
});
}
const dataText = await getDataText(textBlob);File对象与Blob对象转换
document.getElementById('uploadFile').onclick = function() {
const file = document.createElement('input');
file.setAttribute('type', 'file');
// file.setAttribute('accept', 'video/mp4,video/webm,video/ogg');
file.click();
const getFileData = (file) => {
return new Promise((resolve) => {
file.onchange = async function(e) {
resolve(e.target.files[0]);
}
});
}
const fileData = await getFileData(file);
console.info('File对象', fileData);
// File转换为Blob
const fileBlob = new Blob([fileData], {type: fileData.type});
console.info(fileBlob);
// Blob转换为File
const fileData = new File([fileBlob], file.name, {type: file.type});
console.info(fileData);
// 上传文件
const formData = new FormData();
formData.append('file', fileData);
}Base64编码
数据结构
- 图片
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAwAAAAGlCAYAAABNz5H6AAAACXBIWXMAAA7EAAAOxAGVKw4bAAD//0lEQVR4Aey96ZMk23Hll91dvb0VwBDEQpg4w23MJJNJJpP0Rf//R0lfRiMNiY0gsRHkYIiH13t16/yO3xPhERmRmVVd/fAw0u2uuH59d79L7JFX3//v/7d3n3z09PDx06eHq/v3D/cO7w737t07vH331vC7t9SHw713wuvf2+u3alV5K9pb8b958+ZwEP+Dq4eiXx/+9b/8l8O/fvHFQSKHg3RSAF3uyYb+Hj16dPj4k08PTx49cf.....此处省略大量字符串.....AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==- 音频
data:audio/mpeg;base64,SUQzAgAAAAAPdlRDTQAACwH//i6WSU5/YgAAVFQxAAAdAf/+ZGvGiZGYCWdzUUYANQDzl1BOIAAyADEAAABUVDIAABMB//5GADUA85dQTiAAMgAxAAAAVEVOAAAhAFByb1RyYW5zY29kZXJUb29sIChBcHBsZSBNUDMgdjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.....此处省略大量字符串.....AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
简介与核心思想
Base64就是一种基于64个可打印字符来表示二进制数据的方法。
解码和编码 base64 字符串
如果传入字符串不是有效的 base64 字符串,比如其长度不是 4 的倍数,则抛出DOMException。
// 编码
let encodedData = window.btoa("Hello, world");
// 解码
let decodedData = window.atob(encodedData);Blob
注意
File、FileList、FileReader、FileReaderSync继承了Blob, 所以Blob的属性与方法也可以在这些对象中使用。
简介与核心思想
Blob() 构造函数返回一个新的 Blob 对象。 blob的内容由参数数组中给出的值的串联组成。
语法
new Blob(
array, // array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。DOMStrings会被编码为UTF-8
options: { // options 是一个可选的BlobPropertyBag字典,它可能会指定如下两个属性, {}
type: '', // type,默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型。
endings: 'transparent' // endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持blob中保存的结束符不变
}
);Blob属性
Blob.size:Blob 对象中所包含数据的大小(字节)。 Blob.type:一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。
Blob方法
Blob.slice([start[, end[, contentType]]]):返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。 Blob.stream():返回一个能读取blob内容的 ReadableStream。 Blob.text():返回一个promise且包含blob所有内容的UTF-8格式的 USVString。 Blob.arrayBuffer():返回一个promise且包含blob所有内容的二进制格式的 ArrayBuffer
从Blob中读取数据
// 方法一:一种从Blob中读取内容的方法是使用 FileReader。
var reader = new FileReader();
reader.addEventListener("loadend", function() {
// reader.result 包含被转化为类型数组 typed array 的 blob
});
reader.readAsArrayBuffer(blob);
// 方法二:另一种读取Blob中内容的方式是使用Response对象。
var text = await (new Response(blob)).text();代码示例
var debug = {hello: "world"};
var blob = new Blob([JSON.stringify(debug, null, 2)], {type : 'application/json'});
var aFileParts = ['<a id="a"><b id="b">hey!</b></a>']; // 一个包含DOMString的数组
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // 得到 blob
let typedArrayToURL = (typedArray, mimeType) => {
return URL.createObjectURL(new Blob([typedArray.buffer], {type: mimeType}))
// 产生一个类似 blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 这样的URL字符串
}
let bytes = new Uint8Array(59);
for (let i=0; i<59; i++) {
bytes[i] = 32+i;
}
let url = typedArrayToURL(bytes, "text/plain");
let link = document.createElement("a");
link.href = url;
link.innerText = "Open the array URL";
document.body.appendChild(link);html
<input type="file" id="single" onchange="singleFile()">/**
* 大文件分片上传技术
*
*/
//兼容性支持
function blobSlice(blob) {
let blobSlice = blob;
if (blob.mozSlice) { //Firefox 12及更早版本
blobSlice = blob.mozSlice;
}
if (blob.webkitSlice) { //Safari旧版本
blobSlice = blob.webkitSlice;
}
//其他
blobSlice = blob.slice;
//分片技术
return blobSlice;
}
//分片上传
function Burst() {
//
}
let file = document.getElementsByTagName('input')[0];
function singleFile() {
let content = file.files[0];
let size = content.size; //name、size、type、lastModified
console.log('文件分片前大小: ' + size);
let scale = 100 * 1024;
//小于scale,则不分片
if (size > scale) {
//
}
let multiple = Math.ceil(size / scale);
console.log('分片数量:' + multiple);
let remainder = size % scale;
//没有余数,全是倍数
if (remainder == 0) {
//
}
let integer = scale * (multiple - 1);
let total = integer + remainder;
console.log('分片合并后大小:' + total);
//整合分片数据结构
let sliceData = [];
for (let i = 0; i < multiple; i++) {
(function(i) {
let slice = {};
slice['type'] = content.type;
slice['name'] = content.name;
slice['lastModified'] = content.lastModified;
slice['total'] = content.size;
slice['id'] = i;
slice['prev'] = i*scale;
slice['next'] = (i+1)*scale;
slice['blob'] = content.slice(i*scale, (i+1)*scale);
slice['size'] = scale;
//兼容分片不足整数部分
if (i == multiple - 1) {
let last = i*scale + remainder;
slice['next'] = last;
slice['blob'] = content.slice(i*scale, last);
slice['size'] = remainder;
}
sliceData.push(slice);
})(i);
}
recurrence(sliceData);
//decollate(sliceData);
}
//分割上传-递归等待分片上传成功
function recurrence(sliceData) {
sliceData = sliceData || [];
//递归推送, 成功继续推送
let count = 0;
function pushBlob(i) {
//推送完成
if (count == sliceData.length) {
return ;
}
let dx = sliceData[i];
//封装数据
let formData = new FormData();
formData.append("content", dx.blob);
//拼接片段标志参数
let query = "";
for (let i in dx) {
if (i != 'blob') {
query += '&' + i + '=' + dx[i];
}
}
query = query.replace(/^&/, '?');
//开始推送
ajax({
base: 'http://127.0.0.1:7901/',
path: 'decollate' + query,
method: 'post',
type: 'upload',
timeout: 1500000,
size: dx.size,
data: formData,
complete() {},
success(res) {
//继续推送下一流
count += 1;
pushBlob(count);
},
fail(err) {
//推送失败,重复推送
pushBlob(count);
}
});
}
pushBlob(count);
}
//分割上传-演示
function decollate(sliceData) {
sliceData = sliceData || [];
sliceData.forEach((dx)=> {
let formData = new FormData();
formData.append("content", dx.blob);
//拼接片段标志参数
let query = "";
for (let i in dx) {
if (i != 'blob') {
query += '&' + i + '=' + dx[i];
}
}
query = query.replace(/^&/, '?');
//推送服务器
ajax({
base: 'http://127.0.0.1:7901/',
path: 'decollate' + query,
method: 'post',
type: 'upload',
timeout: 1500000,
size: dx.size,
data: formData,
complete() {},
success(res) {
//console.log(res);
},
fail(err) {
//console.log(err);
}
});
});
}实践运用
断点续传
# 断点续传 • 上传
> 见Blob部分
# 断点续传 • 下载
> 注意Response Headers响应头的几个字段
# 告诉服务器从什么字节开始,而不是全部下载
Range: bytes=2000070-
# 完整
Range: bytes=startOffset-targetOffset/sum [表示从startOffset读取,一直读取到targetOffset位置,读取总数为sum直接]
Range: bytes=startOffset-targetOffset [字节总数也可以去掉]
# 服务器响应
HTTP/1.1 206 Partial Content
Content-Range=bytes 2000070-106786027/106786028下载文件
下载单一文件
document.getElementById("singleDownload").addEventListener(
"click",
() => {
let a = document.createElement("a");
let url = "http://test.ysunlight.com/static/images/345.jpeg";
a.setAttribute("download", "test.jpg");
a.href = url;
a.click();
a.remove();
},
false,
);
// 下载图片
async function downloadImage(image) {
const link = URL.createObjectURL(image);
const a = document.createElement("a");
a.download = "activity-share-" + Date.now() + ".png";
a.href = link;
var fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.style.display = "none";
fileInput.webkitdirectory = link;
document.body.appendChild(fileInput);
a.click();
a.remove();
document.body.removeChild(fileInput);
window.URL.revokeObjectURL(link);
}批量下载文件
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Axios | 批量下载</title>
<link
rel="stylesheet"
href="http://test.ysunlight.com/public/style/default.css"
/>
<link
rel="stylesheet"
href="http://test.ysunlight.com/public/style/public.css"
/>
<style type="text/css">
ul > li {
float: left;
}
</style>
</head>
<body data-url="http://test.ysunlight.com/WEB/ajax/批量下载.html">
<div>
<p>http://test.ysunlight.com/Reference/images/111.jpg</p>
<p>http://test.ysunlight.com/Reference/images/141_1443.jpg</p>
<button onclick="downloadImage()" type="button">批量打包下载</button>
</div>
<div>
<p>http://test.ysunlight.com/Reference/document/doc/常用资料 (1).doc</p>
<p>http://test.ysunlight.com/Reference/document/doc/常用资料 (2).doc</p>
<button onclick="downloadFile" type="button">批量打包下载</button>
</div>
</body>
<script src="http://test.ysunlight.com/WEB/ajax/axios/source/axios.min.js"></script>
<script src="http://test.ysunlight.com/WEB/ajax/jszip/dist/jszip.min.js"></script>
<script src="http://test.ysunlight.com/WEB/ajax/file-saver/dist/FileSaver.min.js"></script>
<script type="module">
import {
GET,
POST,
UPLOAD,
DOWNLOAD,
} from "http://test.ysunlight.com/WEB/ajax/axios/axios.api.js";
import { GenerateImageData } from "/public/module/image.js";
import { ImageCanvasBase64 } from "/public/module/imageCanvasBase64.js";
// 批量下载图片
// const imageArray = [
// 'http://test.ysunlight.com/Reference/images/111.jpg',
// 'http://test.ysunlight.com/Reference/images/141_1443.jpg'
// ];
const imageArray = [
"http://test.ysunlight.com/Reference/document/doc/常用资料 (1).doc",
"http://test.ysunlight.com/Reference/document/doc/常用资料 (2).doc",
];
function download(url) {
return new Promise((resolve, reject) => {
DOWNLOAD(url)
.then((res) => {
resolve(res);
})
.catch(() => {
reject(null);
});
});
}
// 批量下载文件
async function downloadFile() {
var zip = new JSZip();
for (let i = 0; i < imageArray.length; i++) {
const file = imageArray[i]
.split("/")
[imageArray[i].split("/").length - 1].split("?")[0];
const result = await download(imageArray[i]);
zip.file(file, result, { binary: true });
console.log(result);
}
zip.generateAsync({ type: "blob" }).then(function (content) {
saveAs(content, `${Date.now()}.zip`);
});
}
// 批量下载图片
async function downloadImage() {
var zip = new JSZip();
for (let i = 0; i < imageArray.length; i++) {
const { image } = await GenerateImageData(imageArray[i]);
if (!image) return;
const imageDt = await ImageCanvasBase64(image);
const file = imageArray[i]
.split("/")
[imageArray[i].split("/").length - 1].split("?")[0];
zip.file(file, imageDt.split(",")[1], { base64: true });
}
zip.generateAsync({ type: "blob" }).then(function (content) {
saveAs(content, `${Date.now()}.zip`);
});
}
</script>
</html>