Angular与Nestjs的文件流传输(SSE)

概述SSE

(Server-Sent Events)是一种用于实现服务器主动向客户端推送数据的技术,也被称为"事件流"(Event Stream)。它基于 HTTP 协议,利用了其长连接特性,在客户端与服务器之间建立一条持久化连接,并通过这条连接实现服务器向客户端的实时数据推送。

实例

使用生成事件的脚本 URL 创建一个 EventSource 对象,用来开启与服务器的连接并从中接收事件。

TS 复制代码
const eventSource = new EventSource(url, configuration);
  • url:一个USVString ,它代表远程资源的位置

  • configuration : 为配置新连接提供选项:

    • withCredentials,默认为 false,指示 CORS 是否应包含凭据 ( credentials )。

属性

eventSource.readyState:只读属性 返回一个表示连接状态的数字

  • 0--- 连接
  • 1- 打开
  • 2--- 关闭

eventSource.url:只读属性 返回一个表示源 URL 的字符串。

eventSource.withCredentials:只读属性 返回一个布尔值,指示该EventSource对象是否是使用 CORS 凭据集实例化的。

方法

当通过事件源接收到数据时,将触发 APImessage的事件

Ts 复制代码
interface MessageEvent{
data:string,//消息发送器发送的数据。
origin,//表示消息发射器来源的字符串。
lastEventId,//表示事件的唯一 ID 的字符串。
source,//代表消息发射器的A `MessageEventSource`(可以是WindowProxy、MessagePort)或对象ServiceWorker
ports//表示与发送消息的通道关联的端口的对象数组(在适当的情况下,例如在通道消息传递中或向共享工作线程发送消息时)。
}

evtSource.onmessage = function (event:MessageEvent) {}

当打开与事件源的连接时,将触发 APIopen的事件

javascript 复制代码
evtSource.addEventListener("open", (e) => {
  console.log("The connection has been established.");
});

当与事件源的连接无法打开时,会触发 APIerror的事件

Ts 复制代码
//当发生错误时(例如网络超时或与访问控制有关的问题),会生成一个错误事件。
evtSource.onerror = (err) => {
  console.error("EventSource failed:", err);
};

该接口close() 的方法EventSource 会关闭连接(如果已建立),并将属性设置 EventSource.readyState2(关闭)。

Ts 复制代码
//关闭事件流
//默认情况下,如果客户端和服务器之间的连接关闭,则连接将重新启动。
evtSource.close();

nestjs后端

今天公司有一个新的需求就是将一个40M的json文件发送到前端中去,这时就可以使用SSE进行流传输了,切片+压缩+流传输 搞定!!!

Ts 复制代码
  sseV2(@Res() res: FastifyReply): Observable<MessageEvent> {
    const faguiJson = join(process.cwd(), './src/xiaoxiao.json');//数据就是一个普通的json数据
    const readJson = fs.readFileSync(faguiJson, 'utf-8');
    const jsonData = JSON.parse(readJson);
    const eventChunks = jsonData.data;

    const chunkSize = 1; // 每次发送的数据块大小
    
    //要是有更好的方案 各位掘友们一定要提点提点我丫 我实在是想不出更快的方案了
    return interval(0).pipe(
      take(Math.ceil(eventChunks.length / chunkSize)),
      map((index) => {
        const start = index * chunkSize;
        const end = Math.min(start + chunkSize, eventChunks.length);
        const chunk = eventChunks.slice(start, end);

        const compressedData = pako.gzip(JSON.stringify(chunk));
        const base64Data = Buffer.from(compressedData).toString('base64');

        return {
          data: base64Data,
        };
      }),
    );
  }

Angular前端

刚开始用angular是实在不适应(而且国内文档教程极其少)但用着用着还真香了,当然了要是搭建一个小项目用vue就足够了,angular还是比较适合大型项目

这里我就直接贴代码了

Ts 复制代码
private eventSource!: EventSource;
  constructor( private ngZone: NgZone) {}
  ngOnInit(): void {
    this.eventSource = new EventSource('/api/item/sseV2');
    this.eventSource.onmessage = (event) => {
      const base64EncodedData = event.data;
      
      // 将base64编码的数据转换成原始的压缩数据
      const compressedData = new Uint8Array(
        atob(base64EncodedData)
          .split('')
          .map((char) => char.charCodeAt(0))
      );

      // 对压缩数据进行解压缩处理
      const data = JSON.parse(pako.ungzip(compressedData, { to: 'string' }));
      //这里有个坑 如果不提醒视图需要更新的话是不会分段加载数据的 
      // 有没有大佬能指点下 有没有更好的方案 让视图更新
      this.ngZone.run(() => {
        this.receivedData.push(...data);
      });
    };
    this.eventSource.onerror = (error) => {
      console.log(error);
      console.log('An error occurred while attempting to connect.');
      this.eventSource.close();
    };
  }

当然还是有一个问题,EventSource不支持传入headers,也就无法传给服务端token。这时候 EventSourcePolyfill就来了

Ts 复制代码
var es = new EventSourcePolyfill('/events', {
  headers: {//设置你所需要的header
    'X-Custom-Header': 'value'
  }
});
相关推荐
kongxx11 天前
NestJS中使用Guard实现路由保护
nestjs
白雾茫茫丶12 天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
nestjs·nest.js·发布订阅·event emitter
lph65821 个月前
比起上传资源更应该懂得如何资源回收
node.js·nestjs
gsls2008081 个月前
将nestjs项目迁移到阿里云函数
阿里云·云计算·nestjs·云函数
d3126975101 个月前
在Nestjs使用mysql和typeorm
mysql·express·nestjs·typeorm
剪刀石头布啊2 个月前
nestjs-版本控制
nestjs
潇洒哥gg2 个月前
重生之我在NestJS中使用jwt鉴权
前端·javascript·nestjs
huangkaihao2 个月前
【NestJS学习笔记】 之 自定义装饰器
前端·node.js·nestjs
鹿鹿鹿鹿isNotDefined2 个月前
Nest 源码解析:依赖注入是怎么实现的?
nestjs
剪刀石头布啊2 个月前
nestjs-自定义装饰器
nestjs