实现图片本地化 ServiceWorker + IndexedDB

共 1724字,需浏览 4分钟

 ·

2022-04-07 21:15

点击上方 前端Q,关注公众号

回复加群,加入前端Q技术交流群

1. 背景

在一些安全场景,或者一些本地化的场景(如本地化的 Markdown 记事本),如果有图片上传并需要查看的场景,在不上传到服务器的情况下,实现这个效果,通常是把图片 Base64 化,但编码后的字符串会非常长,体验较差。

这里不妨尝试使用 ServiceWorker + IndexedDB 来解决这个问题。

2. API 优势

IndexedDB 几乎什么都可以存储,二进制类的文件更不在话下,且存储空间在大多数浏览器中,是和系统空间持平的。

ServiceWorker 可以做页面的网络代理层,所以就不需要 Base64 化了,可以直接写一个特定规则的图片地址,实现从 IndexedDB 中 读/写 文件。

3. 实现

例如把这种特殊的图片采用 .dbimg 后缀。

上传图片时,就可以通过拦截上传请求的方式实现,流程如下:

image
self.addEventListener("fetch", (e) => {
  const url = e.request.url;

  if (e.request.method == "POST" && url.indexOf("update-img") > -1) {
    e.respondWith(
      e.request.formData().then((data) => {
        const file = data.get("img");
        const name = Date.now() + Math.random().toString().substr(24);

        db.put("img", { name, file });
        return new Response(
          JSON.stringify({
            name: name + ".dbimg",
          })
        );
      })
    );
  }
});
复制代码

读取时,通过判断 .dbimg 后缀实现,流程如下:

image
self.addEventListener("fetch", (e) => {
  const url = e.request.url;

  if (e.request.method == "GET" && url.substr(url.length - 6) == ".dbimg") {
    const name = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));

    e.respondWith(
      db
        .getAllMatching("img", { index"name"query: IDBKeyRange.only(name) })
        .then((data) => {
          if (data.length) {
            return new Response(data[0].file);
          }

          return new Response("", { status404 });
        })
    );
  }
});
复制代码

4. 效果

体验地址:lecepin.github.io/file-proxy-…[1]

⭐ 仓库地址:github.com/lecepin/fil…[2]

image
image
image

关于本文

作者:lecepin

https://juejin.cn/post/7075650171471659015



往期推荐


(字节/华为/美团)前端面经记录冷冷清清的金三银四
秒啊!答好这5个问题,就入门Docker了
Vue3!焕然一新的 Vue3 中文文档来了!

最后


  • 欢迎加我微信,拉你进技术群,长期交流学习...

  • 欢迎关注「前端Q」,认真学前端,做个专业的技术人...

点个在看支持我吧
浏览 79
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报