此问题说简单也简单说复杂也复杂,衍生的知识点还是相对多一点点
以下列出参考文章,有助于理解整体思路和概念
参考文章:
- JS二进制文件转换:File、Blob、Base64、ArrayBuffer : https://www.cnblogs.com/yinpengfei/p/17280585.html
- arraybuffer、Blob、File、Buffer详解、作用以及相互转化 https://zhuanlan.zhihu.com/p/376721544
概念解释
首先,我们要清楚,在 Js向后端请求的过程中, Response 会产生哪些类型
我们可以打开 MDN responseType介绍查看 :https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/responseType
- arrayBuffer:
- blob
- json
- text
我们只需要关系这四种即可
作为请求方式,我们可以多种方式来获取对应的 responseType 数据,这里列出 axios 和 fetch文档
- Axios:https://www.axios-http.cn/docs/req_config
- Fetch:https://developer.mozilla.org/zh-CN/docs/Web/API/Response/arrayBuffer
我们以 Fetch 举例,我们可以通过
response.arrayBuffer().then(function(buffer) {
// do something with buffer
)}; 轻而易举的拿到对应 类型数据
其实我觉得挺难理解为什么需要 arrayBuffer 或者 blob,直接使用json 或者 text 不可以吗
的确,大部分数据使用这两种类型可以实现,但是我们必须考虑一些问题
比如
- 文件 :二进制存在
- 加密数据:乱码不现实
- 资源: 二进制
- 多平台跨对象传输
以上几种,最终都要用到 arrayBuffer,也就是二进制的实现,最简单的 0 和 1 在任何地方都能保证数据的有效兼容
如何实现文件流下载
这里我们使用 fetch来实现
例子一
const downloadAvatar = () => {
const url =
"https://avatars.githubusercontent.com/u/29169847?v=4&size=64";
const contentType = "image/png";
fetch(url)
.then((res) => res.arrayBuffer())
.then((buffer) => {
const blob = new Blob([buffer], { type: "image/png" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "头像.png";
a.click();
URL.revokeObjectURL(url);
});
};
document.querySelector("button").addEventListener("click", function (e) {
e.preventDefault();
downloadAvatar();
return false;
});
可以看到,我们通过检测其 content-type,然后将 arrayBuffer 转为 blob 并最后得到一个 objectUrl 最终实现下载
当然这是一个最简单的例子
例子二
现在我们要升级,后端返回的数据可能是json 可能是 text 也可以能是其他乱七八糟的,我们希望根据不同的类型定义去走不同的逻辑
const url =
"https://avatars.githubusercontent.com/u/29169847?v=4&size=64";
fetch(url)
.then((res) => {
const contentType = res.headers.get("content-type");
if (contentType && contentType.includes("application/json")) {
return res.json();
}
return res.arrayBuffer();
})
.then((data) => {
if (data instanceof ArrayBuffer) {
// 处理二进制数据
const blob = new Blob([data], { type: "image/png" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "头像.png";
a.click();
URL.revokeObjectURL(url);
} else {
// 处理 JSON 数据
console.log("收到 JSON 数据:", data);
// 这里可以根据 JSON 数据的内容执行不同的逻辑
if (data.error) {
alert("下载失败: " + data.error);
} else if (data.avatarUrl) {
// 如果 JSON 中包含头像 URL,继续下载
downloadAvatarFromUrl(data.avatarUrl);
}
}
})
.catch((error) => {
console.error("下载失败:", error);
alert("下载失败,请稍后重试");
});
};
我们可以通过 Response contentType 判断数据类型来实现逻辑处理
例子三
const url =
"https://raw.githubusercontent.com/surest-sky/surest-sky/refs/heads/main/README.md";
fetch(url)
.then((res) => res.arrayBuffer())
.then((buffer) => {
console.log(buffer);
const decoder = new TextDecoder();
const text = decoder.decode(buffer);
console.log(text);
})
.catch((error) => {
console.error("下载失败:", error);
});
虽然我们返回的依旧是arrayBuffer,但是我们可以通过 TextDecoder来进行解析,最后得到一个实际的text内容
本文由 邓尘锋 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Dec 27, 2024 at 11:32 pm