>웹 프론트엔드 >JS 튜토리얼 >nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

青灯夜游
青灯夜游앞으로
2022-01-17 19:16:383315검색

기반 node 대용량 파일을 전송하기 위해 http를 구현하는 방법은 무엇입니까? 다음 글에서는 nodejs를 기반으로 한 몇 가지 실용적인 http 파일 전송 솔루션을 소개하겠습니다. 도움이 되길 바랍니다!

nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

nodejs 기반의 http 파일 전송 솔루션은 현재 프런트엔드 및 백엔드 풀 스택 개발에서 매우 중요한 역할을 합니다. 이 기사에서는 여러 솔루션을 사용하여 대규모 http 전송을 구현하겠습니다. 파일. 함수를 구현하기 전에 먼저 nodejs의 fs 모듈을 통해 대용량 파일을 작성하고 프로젝트에 로컬 파일을 생성합니다.

const fs = require('fs');
const writeStream = fs.createWriteStream(__dirname + "/file.txt");
for(let i = 0;i <= 100000; i++) {
  writeStream.write(`${i} —— 我是${i}号文件\n`, "utf-8");
}
writeStream.end();

nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

위 코드가 성공적으로 실행되면 현재 실행 디렉터리에 크기가 생성됩니다. 다음 솔루션의 "대형 파일 자료"로 사용되는 3.2MB 크기의 텍스트 파일입니다. 대용량 파일 전송 체계를 나열하기 전에 먼저 나중에 사용할 두 가지 공개 방법인 파일 읽기 방법파일 압축 방법을 캡슐화합니다. 文件读取方法文件压缩方法

// 封装读取文件的方法
const readFile = async (paramsData) => {
  return new Promise((resolve, reject) => {
    fs.readFile(paramsData, (err, data) => {
      if(err) {
        reject(&#39;文件读取错误&#39;);
      } else {
        resolve(data);
      }
    })
  })
}

// 封装文件压缩方法
const gzip = async (paramsData) => {
  return new Promise((resolve, reject) => {
    zlib.gzip(paramsData, (err, result) => {
      if(err) {
        reject(&#39;文件压缩错误&#39;);
      } else {
        resolve(result);
      }
    })
  })
}

1. 通过大文件在数据压缩后传输

浏览器在发送请求时,都会携带 accept 和 accept-* 请求头信息,用于告诉服务器当前浏览器所支持的文件类型、支持的压缩格式列表和支持的语言。请求头中的 Accept-Encoding 字段,用于将客户端能够理解的内容编码方式(通常是某种压缩算法)告诉给服务端。服务端会选择一个客户端所支持的方式,并通过响应头 Content-Encoding 来通知客户端该选择,响应头告诉浏览器返回的 JS 脚本,是经过 gzip 压缩算法处理过的

// 请求头
accept-encoding: gzip, deflate, br
// 响应头
cache-control: max-age=2592000 
content-encoding: gzip 
content-type: application/x-javascript

基于 Accept-Encoding 和 Content-Encoding 字段的了解,我们来验证一下未开启 gzip 和开启 gzip 的效果。

// 实现一个简单的文件读取服务器(没有开启gzip)
const server = http.createServer(async (req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/plain;charset=utf-8",
  });
  const buffer = await readFile(__dirname + &#39;/file.txt&#39;);
  res.write(buffer);
  res.end();
})
server.listen(3000, () => {
  console.log(`server启动成功`)
})

nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

// 实现一个简单的文件读取服务器(开启gzip)
const server = http.createServer(async(req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/plain;charset=utf-8",
    "Content-Encoding": "gzip"
  });
  const buffer = await readFile(__dirname + &#39;/file.txt&#39;);
  const gzipData = await gzip(buffer);
  res.write(gzipData);
  res.end();
})
server.listen(3000, () => {
  console.log(`server启动成功`)
})

nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)

2. 通过数据分块传输

有场景需要用从数据库中查询获得的数据生成一个大的 HTML 表格的时候,或者需要传输大量的图片的时候,可以通过分块传输实现。

Transfer-Encoding: chunked
Transfer-Encoding: gzip, chunked

响应头 Transfer-Encoding 字段的值为 chunked,表示数据以一系列分块的形式进行发送。需要注意的是 Transfer-Encoding 和 Content-Length 这两个字段是互斥的,也就是说响应报文中这两个字段不能同时出现。

// 数据分块传输
const spilitChunks = async () =>{
  const buffer = await readFile(__dirname + &#39;/file.txt&#39;);
  const lines = buffer.toString(&#39;utf-8&#39;).split(&#39;\n&#39;);
  let [chunks, i, n] = [[], 0, lines.length];
  while(i < n) {
    chunks.push(lines.slice(i, i+= 10));
  };
  return chunks;
}
const server = http.createServer(async(req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/plain;charset=utf-8",
    "Transfer-Encoding": "chunked",
    "Access-Control-Allow-Origin": "*",
  });
  const chunks = await spilitChunks();
  for(let i =0; i< chunks.length; i++) {
    setTimeout(() => {
      let content = chunks[i].join("&");
      res.write(`${content.length.toString(16)}\r\n${content}\r\n`);
    }, i * 1000);
  }
  setTimeout(() => {
    res.end();
  }, chunks.length * 1000);
})
server.listen(3000, () => {
  console.log(`server启动成功`)
})

3. 通过数据流的形式传输

当使用 Node.js 向客户端返回大文件时,使用流的形式来返回文件流能避免处理大文件时,占用过多的内存。具体实现方式如下所示。当使用流的形式来返回文件数据时,HTTP 响应头 Transfer-Encoding 字段的值为 chunked

const server = http.createServer((req, res) => {
  res.writeHead(200, {
    "Content-Type": "text/plain;charset=utf-8",
    "Content-Encoding": "gzip",
    "Transfer-Encoding": "chunked"
  });
  fs.createReadStream(__dirname + "/file.txt")
    .setEncoding("utf-8")
    .pipe(zlib.createGzip())
    .pipe(res);
})

server.listen(3000, () => {
  console.log(`server启动成功`)
})

1. 데이터 압축 후 대용량 파일을 통해 전송

브라우저가 요청을 보내면 accept accept-가 전달됩니다. * 현재 브라우저에서 지원하는 파일 형식, 지원되는 압축 형식 목록 및 지원되는 언어를 서버에 알리는 데 사용되는 헤더 정보를 요청합니다. 요청 헤더의 Accept-Encoding 필드는 클라이언트가 이해할 수 있는 콘텐츠 인코딩 방법(일반적으로 특정 압축 알고리즘)을 서버에 알리는 데 사용됩니다. 서버는 클라이언트가 지원하는 방법을 선택하고 Content-Encoding 응답 헤더를 통해 클라이언트에게 선택 사항을 알립니다. 응답 헤더는 반환된 JS 스크립트가 gzip을 통해 전달되었음을 브라우저에 알려줍니다. 압축 알고리즘 처리 🎜rrreeerrreee🎜 Accept-EncodingContent-Encoding 필드에 대한 이해를 바탕으로 gzip가 아닌지 확인 켜짐 > 및 gzip 켜짐의 효과. 🎜rrreee🎜nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)🎜rrreee 🎜🎜🎜🎜2. 데이터 청크를 통한 전송🎜🎜🎜데이터베이스 쿼리에서 얻은 데이터를 사용하여 대규모 HTML 테이블을 생성해야 하거나 대규모 HTML 테이블을 생성해야 하는 경우가 있습니다. 전송해야 하는 데이터의 양 사진은 청크로 전송될 수 있습니다. 🎜rrreee🎜응답 헤더의 Transfer-Encoding 필드 값은 청크입니다. 이는 데이터가 일련의 청크로 전송된다는 의미입니다. Transfer-EncodingContent-Length 두 필드는 상호 배타적입니다. 즉, 이 두 필드는 응답 메시지에 동시에 나타날 수 없습니다. 🎜rrreee🎜🎜3. 데이터 스트림을 통한 전송🎜🎜🎜 Node.js를 사용하여 대용량 파일을 클라이언트에 반환하는 경우 스트림을 사용하여 파일 스트림을 반환하면 대용량 파일을 처리할 때 너무 많은 메모리를 차지하는 것을 피할 수 있습니다. 구체적인 구현은 다음과 같습니다. 스트림을 사용하여 파일 데이터를 반환하는 경우 HTTP 응답 헤더 Transfer-Encoding 필드의 값이 청크로 표시되어 데이터가 일련의 청크로 전송됨을 나타냅니다. 🎜rrreee🎜노드 관련 지식을 더 보려면 🎜nodejs 튜토리얼🎜을 방문하세요! ! 🎜

위 내용은 nodejs를 기반으로 대용량 파일의 HTTP 전송을 구현하는 방법은 무엇입니까? (실천적인 방법 공유)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제