記事ディレクトリ
この記事では、URL からファイルへの変換、base64 への変換、ファイルから BLOB タイプへの変換など、画像ファイルの処理に焦点を当てています。
注意
: Base64 形式は本質的に非常に長い文字列であるため、ビデオ ファイルを Base64 に変換しないでください。より大きなビデオ ファイルを携帯電話にアップロードして保持すると、ページが自動的に更新され、プログラムがクラッシュします。转bsee64的操作
ビデオの Base64 文字列が大きすぎてメモリをサポートできないため、ブラウザさえもシステムによって直接強制終了されます。
ビデオ ファイルをアップロードした後にビデオをエコーしたい場合は、createObjectUrl()
アクセスする一時メモリ アドレスを生成するメソッドを使用できます。
0、序文
JavaScript は、ファイルや生のファイル データを処理するための API (File、Blob、FileReader、ArrayBuffer、base64 など) を提供します。これらを知っておくと、以下のメソッドのいくつかを理解しやすくなります。
以下のブログを読むことをお勧めします
(知乎):1、https://zhuanlan.zhihu.com/p/568915443
(csdn):2、https://blog.csdn.net/mrlaochen/article/details/120209650
1. 画像の URL ネットワーク リンク (http://) を Base64 形式に変換します。
/**
* 将图片的url网络链接(http://) 转为base64格式
* @param {string}
*/
export function imgUrlToBase64(imgUrl) {
return new Promise((resolve) => {
var img = new Image();
img.src = imgUrl;
// 设置图片跨域属性
img.setAttribute("crossOrigin", "anonymous");
// 注意 onload是异步的行为
img.onload = () => {
var canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL("image/png");
resolve(dataURL);
};
});
}
次のように使用します。
// 网络图片链接
let finalImg = "https://img0.baidu.com/it/u=3021883569,1259262591&fm=253&fmt=auto&app=120&f=JPEG?w=1140&h=641";
// 开始使用
imgUrlToBase64(finalImg).then((res) => {
console.log("res:", res);
});
2.base64画像データをファイル化する
/**
* 将以base64的图片数据转换为File文件
* @param {string}
*/
export function base64ToFile(dataUrl, fileName = "myFile") {
let arr = dataUrl.split(",");
let mime = arr[0].match(/:(.*?);/)[1];
let suffix = mime.split("/")[1];
let bstr = atob(arr[1]);
let n = bstr.length;
let u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], `${
fileName}.${
suffix}`, {
type: mime
});
}
使用例:
<input type="file" />
// 原生添加点击事件
document.getElementsByTagName("input")[0].onchange = async function (e) {
// 拿到的文件类型
let file = e.target.files[0];
console.log("file:",file);
// 先转为base64
let base64 = await fileTransferBase64(file);
// 将以base64的图片url数据转换为File文件
let file2 = base64ToFile(base64) ================注意看这行===================
console.log("file2:", file2);
};
3.base64の画像データをBlobに変換する
/**
* 将以base64的图片数据转换为Blob
* @param urlData 用url方式表示的base64图片数据
*/
function base64UrlToBlob(urlData, filename) {
try {
if (urlData == "" || !urlData) {
return console.warn("urlData不存在");
}
if (!filename) {
filename = "myfile";
}
// 以base64的图片url数据转换为Blob
var arr = urlData.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let bold = new Blob([u8arr], {
type: mime });
return {
bold, filename };
} catch (error) {
console.warn("base64转换为Blob出问题了:", error);
}
}
使用例:
<input type="file" />
// 原生添加点击事件
document.getElementsByTagName("input")[0].onchange = async function (e) {
// 拿到的文件类型
let file = e.target.files[0];
console.log("file:", file);
let base64 = await fileTransferBase64(file);
// 将以base64的图片url数据转换为File文件
let blob = base64UrlToBlob(base64); =======注意这行=========
console.log("blob:", blob);
};
4. ファイルをbase64に変換します
/**
* 将file文件转化为base64 使用promise
* @param file 该文件的file类型
*/
export function fileTransferBase64(file) {
try {
return new Promise((resolve, reject) => {
const reader = new FileReader(); //异步读取
reader.readAsDataURL(file);
// 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
reader.onload = (e) => {
resolve(e.target.result);
};
// 失败返回失败的信息
reader.onerror = (error) => {
console.warn('file文件转化为base64s失败:', error);
reject(error);
};
});
} catch (error) {
console.warn('捕获fileTransferBase64方法的错误:', error);
}
}
使用例:
転送ファイルの種類には非同期性が含まれるため、非同期promise
性を使用してカプセル化します。
<input type="file" />
// 原生添加点击事件
document.getElementsByTagName("input")[0].onchange = async function (e) {
// 拿到的文件类型
let file = e.target.files[0];
// 转file类型 涉及到异步 所以要用 promise
let base64 = await fileTransferBase64(file)
console.log("base64:",base64);
};
5. ファイルを BLOB に変換する
/**
* 直接将file数据转换为Blob
* @param file格式
*/
export function fileToBlob(file) {
return new Promise((resolve, reject) => {
// FileReader 异步读取文件
const reader = new FileReader();
// readAsDataURL: dataurl它的本质就是图片的二进制数据, 进行base64加密后形成的一个字符串,
reader.readAsDataURL(file);
// 成功和失败返回对应的信息,reader.result一个base64,可以直接使用
reader.onload = (e) => {
let arr = e.target.result.split(',');
let mime = arr[0].match(/:(.*?);/)[1];
console.log(mime);
const blob = new Blob([e.target.result], {
type: mime });
resolve(blob);
};
// 失败返回失败的信息
reader.onerror = (error) => {
console.warn('file数据转换为Blob失败:', error);
reject(error);
};
});
}
使用例:
BLOB 型の変換には非同期性も伴うため、promise
それをカプセル化するために を使用します。
<input type="file" />
// 原生添加点击事件
document.getElementsByTagName("input")[0].onchange = async function (e) {
// 拿到的文件类型
let file = e.target.files[0];
// 转file类型 涉及到异步 所以要用 promise
let blob = await fileToBlob(file);
console.log("blob:", blob);
};
6. 取得したファイル(写真・ビデオ等)のローカルメモリアドレスに直接アクセス可能
このメソッドは、ファイルのアップロード後にエコーするために使用できます。
/**
* 获取文件(图片视频等)的本地内存地址 可以直接访问
* @param file 该文件的文件流
*/
export function createObjectURLFun(file) {
let url = '';
if (window.createObjectURL != undefined) {
// basic
url = window.createObjectURL(file);
} else if (window.URL != undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file);
}
return url;
}
使用例:
// 原生添加点击事件
document.getElementsByTagName("input")[0].onchange = async function (e) {
// 拿到的文件类型
let file = e.target.files[0];
let objectURL = createObjectURLFun(file)
console.log("objectURL:", objectURL);
//打印结果: objectURL: blob:null/31fff142-4b83-4749-b71d-a9a4f6c16a43
};
7. ビデオ フレーム キャプチャ (ビデオの最初のフレームをキャプチャ)
ビデオ ファイルの最初のフレームは、ビデオ ファイルのアップロード後にインターセプトされ、カバーとして使用されることがよくあります。
最初:
/**
* 获取视频的第一帧 来当做封面
* @param url 视频的url 可以是一个由window.URL.createObjectURL返回的视频内存临时地址(推荐使用)
*/
export function getFirstImg(url) {
return new Promise(function (resolve, reject) {
try {
let dataURL = '';
let width = '90'; // 单位是px 可以随意更改
let height = '90';
let listen = 'canplay';//需要监听的事件
let video = document.createElement('video');
let canvas = document.createElement('canvas');
//使用严格模式
('use strict');
video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
video.setAttribute('src', url);
video.setAttribute('width', width);
video.setAttribute('height', height);
video.currentTime = 1; // 第一帧
video.preload = 'auto'; //metadata:抓取原数据
//判断IOS 监听 durationchange或progress 但是在ios会出现黑屏
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
video.load();
video.autoplay = true;
video.muted = true; //静音
listen = 'loadeddata';
}
// 第二版 dataLoad
video.addEventListener(listen, () => {
console.log("我走了");
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(video, 0, 0, width, height); //绘制canvas
dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
resolve(dataURL);
});
} catch (error) {
console.log('视频截帧的失败报错:', error);
}
});
}
2 番目のタイプ:
export function getFirstImg2(url) {
const video = document.createElement("video");
video.crossOrigin = "anonymous"; // 允许url跨域
video.autoplay = true; // 自动播放
video.muted = true; // 静音
video.src = url;
return new Promise((resolve, reject) => {
try {
video.addEventListener(
"loadedmetadata",
() => {
console.log("loadedmetadata");
video.currentTime = 2;
const canvas = document.createElement("canvas");
video.addEventListener("canplaythrough", () => {
console.log("canplaythrough");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas
.getContext("2d")
.drawImage(video, 0, 0, canvas.width, canvas.height);
const firstFrame = canvas.toDataURL();
// console.log(firstFrame); // 输出第一帧画面的Base64编码字符串
resolve(firstFrame);
});
},
{
once: true }
);
} catch (err) {
console.error(err);
reject("");
}
});
}
8. まとめ
上記のメソッドを使用して非同期操作があることを示す場合は、new Promise
を呼び出すときに.then
変換されたファイルを取得するためにこれらのメソッドを使用する必要があります。または、async await
構文を直接使用してresolve ()
、メソッドによって返されたファイルを受け取ります。
予期しない問題を避けるために、コードが同期的に実行できることを確認してください。