node.js segment point renewal: the implementation method of Nginx configuration file segment download function ﹣ node.js

Keywords: Nginx Vue html5 angular

This tag can be configured in Node.JS to realize the segmented download of files. This article introduces Node.JS segment point continuation: the implementation method of Nginx configuration file segment download function. Please refer to it for your reference.

Html5 provides a new Range tag to implement the segmented download of files. This tag can be configured in Node.JS to realize the segmented download of files.

Header tag

Request Header: download file content after 3744

range: bytes=3744-

Return Response Header: the total length of the file is 15522643 bytes

accept-ranges': 'bytes'

content-range': 'bytes */15522643'

Nginx configuration

First, configure Nginx to support range tag return. Simply add add header accept ranges bytes; this line is enough.

server {

 listen 80;

 server_name adksdf.com;

 location ~ ^/(img/|js/|css/|upload/|font/|fonts/|res/|icon) {

  add_header Access-Control-Allow-Origin *;

  add_header Accept-Ranges bytes;

  root /var/www/...;

  access_log off;

  expires max;

 }

 ...

}

After enabling, if node.js sends the request information with range header, nginx will return the information with range:

This is a complete Response Header. Note that the content length here is not the total length of the file, but the length of the current range.

{ server: 'nginx',

 date: 'Wed, 24 Jan 2018 02:43:20 GMT',

 'content-type': 'application/zip',

 'content-length': '12420187',

 'last-modified': 'Tue, 16 Jan 2018 12:09:47 GMT',

 connection: 'close',

 etag: '"5a5deb8b-ecdb53"',

 expires: 'Thu, 31 Dec 2037 23:55:55 GMT',

 'cache-control': 'max-age=315360000',

 'access-control-allow-origin': '*',

 'accept-ranges': 'bytes',

 'content-range': 'bytes 3102456-15522642/15522643' }

The total size of the file can be obtained according to the content range in the header.

Node.JS implementation

This example first detects the lower half of the local file, then creates a file stream in 'r +' read-write mode, and writes the response stream to the file.

Here you will add support for range to the statement file.

var reqOptions = { url: packageUrl, headers: {} }

var filepath  = '/path/to/your/part/file'

var fileOptions = {}

fs.stat(filepath, function(err, states) {

 if (states) {

  //Range: bytes=3744-

  reqOptions.headers['range'] = 'bytes=' + states.size + '-'

  fileOptions = { start: states.size, flags: 'r+' }

 }

 //Create http object method

 var reqUrl = reqOptions.url

 var urlObj = url.parse(reqUrl)

 var options = {

   hostname : urlObj.hostname

  , port   : urlObj.port

  , path   : urlObj.pathname

  , headers  : reqOptions.headers || {}

 }

 var req = http.request(options, function(res) {

  var receives  = []

  var err     = null

  var statusCode = res.statusCode

  var headers   = res.headers

  var ws = fs.createWriteStream(filepath, fileOptions)

  ws.on('error', function(e) {

   console.log('ws error', e)

  })

  res.on('data', function(chrunk) {

   ws.write(chrunk)

  })

  res.on('error', function(err) {

   ws.end()

  })

  res.on('end', function() {

   ws.end()

  })

 })

 req.on('error', function(e) {

  cb && cb(e, null, {})

 })

 req.end()

 ...

})

Return to Header

In the request nginx may return other status code s, such as 206 or 416, meaning as follows:

206 Partial Content

Part of the file content is returned

416 Requested Range Not Satisfiable

Requested range exceeds file size

The above is for you. I hope it will help you in the future.

Related articles:

vue multi entry file building example of vue multi page building

An angular method level cache annotation (decorator)

Solve the problem of not refreshing the page data when the route of vue changes

Encountered in project:

downloadFilePart :function(uri,uridownload,filename,event) {
  var request = require('request')
  const SINGLE = 1024 * 1024 * 1024 ;
  const file =path.join(store.globalData.storePath, filename);
  var fs = require('fs');
  request(
    {
    method: 'GET',
    uri: uri,
    }, 
    (err, res) => {
    const size = Number(res.headers['content-length']); 
    let length = 1;
    if (size>SINGLE) {
      length = parseInt(size / SINGLE)+1;
    }
    var num = 0;
    for (let i=0; i<length;i++) {
      let start = i * SINGLE;
      let end = i == length-1 ?  size - 1: (i + 1) * SINGLE - 1;
      request({
        method: 'GET',
        uri: uridownload,
        headers: {
            'range': `bytes=${start}-${end}`
        },
      }).pipe(fs.createWriteStream(file, {flags:'w',start, end})).on('close', function (a) {
        num++
        console.info('%c Download backup case data-'+start+'-Time:' + new Date().getTime(), "color:red")
        if (num == length) {//You must accept all requests before sending the download completed return. Otherwise, the zip file data is abnormal.
          event.sender.send('downloadFile-reply', 'success'); // Asynchronous return request
        }
      });
    }
  })
},

Posted by BinaryBird on Thu, 24 Oct 2019 02:42:02 -0700