侧边栏壁纸
博主头像
xuesheng博主等级

分享web知识,学习就是取悦自己!

  • 累计撰写 116 篇文章
  • 累计创建 14 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

记录

xuesheng
2022-09-01 / 0 评论 / 1 点赞 / 348 阅读 / 1,597 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-11-26,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Docker部署项目

Docker-容器化部署前端项目

前端项目打包后,通过构建镜像,创建容器部署。

基本实现

Dockerfile

FROM nginx

COPY  dist /usr/share/nginx/html/

# Copy a configuration file from the current directory
COPY  nginx.conf /etc/nginx/

# RUN service nginx start
# Expose ports
# EXPOSE 80

# ENTRYPOINT ["bash", "/usr/share/nginx/html/changeIP.sh"]

nginx.conf


worker_processes 1;

events { worker_connections 1024; }

http {
    include    mime.types;
    sendfile on;
    server {
        root /usr/share/nginx/html/;
        index index.html;
        server_name localhost;
        listen 80;
        location /nginx_status {
                 stub_status on;
                 # allow 127.0.0.1;  #only allow requests from localhost
                 # deny all;   #deny all other hosts
         }
    }
}

docker-compose.yml

version: '3'

services:
  image_name:
    container_name: c_name
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '5173:5173'

命令

docker compose
docker-compose up -d --build
docker 打包镜像
docker build -t image_name:tag . ->docker build -t my-app:v1 .
docker 镜像压缩包
docker save -o xxx.tar image_name:tag

文件下载

文件分片下载

实现一个文件分片下载案例。
工作中对于下载的方式有很多,可以利用FileSaver插件来实现统一的下载方式,减少多次编写a标签进行下载。

文件下载方式

文件下载常用的方式,列举了直接使用a标签的方式和使用插件的方式。

a标签

设置a标签的dowload属性
调用createObjectURL方法创建blob的下载链接
执行a标签的click事件
最后调用revokeObjectURL移出内部映射,释放内存

const a = document.createElement("a");
a.download = filename;
a.href = URL.createObjectURL(blob);
a.click();
URL.revokeObjectURL(a.href)

FileSaver.js

FileSaver.js是客户端解决保存文件的一个解决方案,在项目中引入该JS库,利用统一方式进行文件保存。

import { saveAs } from 'file-saver';
FileSaver saveAs(
  Blob/File/Url, 
  optional DOMString filename, 
  optional Object { autoBom }
)
方案1

保存文件时,如果浏览器环境支持a标签的download属性,且非macos webview环境下,会优先使用a.download来进行文件保存。

字符串类型

FileSaver源码内部多了一层CORS机制的判断。

saveAs('http://xxx.xxx...')

function saveAs(blob, name, opts) {
  var URL = _global.URL || _global.webkitURL;
  var a = document.createElement("a");
  name = name || blob.name || "download";

  a.download = name;
  a.rel = "noopener";

  if (typeof blob === "string") {
    a.href = blob;
    if (a.origin !== location.origin) { // (1)
      corsEnabled(a.href)
        ? download(blob, name, opts)
        : click(a, (a.target = "_blank"))
    } else { // (2)
      click(a);
    }
  } else {
  	...
  }
}
CORS判断

通过corsEnabled方法来判断是否支持CORS机制。
corsEnabled方法通过XMLHttpRequest API 来发起 HEAD 请求,判断请求返回的状态码区间是否在[200-299]

download方法和click方法都是FileSaver内部方法。

download

download方法通过 XMLHttpRequest API 来发起 HTTP 请求,响应类型为 blob,然后调用自身saveAs方法来进行资源下载。

click

click方法通过node对象来派发点击事件,来实现不支持 CORS 机制或同域的情形

blob类型

blob类型主要是通过createObjectURL方法来创建资源对象链接,实现资源下载。

saveAs(blob)

function saveAs(blob, name, opts) {
  var URL = _global.URL || _global.webkitURL
  var a = document.createElement("a")
  name = name || blob.name || "download"

  a.download = name;
  a.rel = "noopener";

  if (typeof blob === "string") {
     // 省略处理字符串类型参数
  } else {
    a.href = URL.createObjectURL(blob);
    setTimeout(function () {
      URL.revokeObjectURL(a.href);
    }, 4e4); // 40s
    setTimeout(function () {
      click(a)
    }, 0);
  }
}
方案2

IE10 浏览器中,msSaveBlobmsSaveOrOpenBlob方法允许用户在客户端上保存文件

blob类型

在满足 “msSaveOrOpenBlob” in navigator 条件时, FileSaver.js 会使用方案2来实现文件保存

function saveAs(blob, name, opts) {
  name = name || blob.name || "download";
  if (typeof blob === "string") {
    ...
  } else {
    navigator.msSaveOrOpenBlob(bom(blob, opts), name)
  }
}
方案3

方案1和方案2都不支持的话,FileSaver.js 就会使用 FileReader API 和 open API 新开窗口来实现文件保存。

blob类型

在其他方案都无法使用的情况下,FileSaver 会使用 FileReader API 先把 Blob 对象转换为 Data URL,然后再把该 Data URL 地址赋值给新开的窗口或当前窗口的 location 对象

使用FileSaver插件,可以应对多种环境的文件下载。

文件分片下载

HTTP头部添加Range,通知服务器返回范围内的文件。

代码实现

获取文件大小

通过HEAD请求来获取content-length

/**
 * 获取文件大小
 */
const getContentLength = async url => {
  const res = await request({
    url,
    method: 'HEAD'
  })
  return res.headers['content-length']
}
下载并发控制

插件 asyncPool

/**
 * 并发控制
 */
const ReqAsyncPool = async (...args) => {
  const allArray = []
  for await (const ms of asyncPool(...args)) {
    allArray.push(ms)
  }

  return allArray
}
指定请求范围

指定请求文件的范围 range ,响应为 arraybuffer

/**
 * 文件范围控制
 */
const getBinaryContent = async (url, start, end) => {
  const res = await request({
    url,
    method: 'GET',
    headers: {
      Range: `bytes=${start}-${end}`
    },
    responseType: 'arraybuffer'
  })
  return { buffer: res.data }
}
文件合并

arraybuffer转换为 Unit8Array,进行合并操作


/**
 * 文件合并
 */
const concatenate = (arrays) => {
  if (!arrays.length) return null;
  let totalLength = arrays.reduce((acc, value) => acc + value.length, 0);
  let result = new Uint8Array(totalLength);
  let length = 0;
  for (let array of arrays) {
    result.set(array, length);
    length += array.length;
  }
  return result;
}
文件保存

FileSaver可以快速进行Blob类型的存储。


/**
 * 文件保存
 */
const fileSave = ({ name, sortedBuffers,  mime = "application/octet-stream" }) => {
  const blob = new Blob([sortedBuffers], { type: mime });
  // 使用 saveAs
  saveAs(blob, name)
}
下载事件
/**
 * 下载
 */
const downloadFile = async () => {
  const url = 'http://xxx.xxx'
  // 1. 文件大小
  const contentLength = await getContentLength(url)

  // 2. 文件分片数量
  const chunks =
    typeof chunkSize === 'number' ? Math.ceil(contentLength / chunkSize) : 1

  // 3. 并发请求
  const res = await ReqAsyncPool(
    3,
    [...new Array(chunks).keys()],
    i => {
      let start = i * chunkSize
      let end = i + 1 == chunks ? contentLength - 1 : (i + 1) * chunkSize - 1
      return getBinaryContent(start, end, i)
    }
  )
  // 4. arraybuffer -> Unit8Array
  const sortedBuffers = res
    .map((item) => new Uint8Array(item.buffer));
  // 5. 合并
  const concatenateData = concatenate(sortedBuffers)
  fileSave({name: 'qjtp.jpg', sortedBuffers: concatenateData, mime: "image/jpeg" })
}

模拟下载

使用Koakoa-range中间件。

文件分片下载流

在文件下载时,保存的分片都在内存,在最后读取内存中的分片,进行文件合并,如果下载的文件非常大,直接生成的Blob很大,那么浏览器内存是不够用来分片缓存的,需要更换分片保存的方法。

FileSaver.js的仓库文档

If you need to save really large files bigger than the blob’s size limitation or don’t have enough RAM, then have a look at the more advanced StreamSaver.js that can save data directly to the hard drive asynchronously with the power of the new streams API

如果有超大文件,可以使用StreamSaver来保存大文件。

1

评论区