FileDownloader.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. const axios = require('axios');
  2. const userAgent = 'Mozilla/5.0 (X11; HasCodingOs 1.0; Linux x64) AppleWebKit/637.36 (KHTML, like Gecko) Chrome/70.0.3112.101 Safari/637.36 HasBrowser/5.0';
  3. class FileDownloader {
  4. constructor(limitDownloadSize = 0) {
  5. this.limitDownloadSize = limitDownloadSize;
  6. }
  7. async load(url, callback, abort) {
  8. let errMes = '';
  9. const options = {
  10. headers: {
  11. 'user-agent': userAgent
  12. },
  13. responseType: 'stream',
  14. };
  15. try {
  16. const res = await axios.get(url, options);
  17. let estSize = 0;
  18. if (res.headers['content-length']) {
  19. estSize = res.headers['content-length'];
  20. }
  21. if (this.limitDownloadSize && estSize > this.limitDownloadSize) {
  22. throw new Error('Файл слишком большой');
  23. }
  24. let prevProg = 0;
  25. let transferred = 0;
  26. const download = this.streamToBuffer(res.data, (chunk) => {
  27. transferred += chunk.length;
  28. if (this.limitDownloadSize) {
  29. if (transferred > this.limitDownloadSize) {
  30. errMes = 'Файл слишком большой';
  31. res.request.abort();
  32. }
  33. }
  34. let prog = 0;
  35. if (estSize)
  36. prog = Math.round(transferred/estSize*100);
  37. else
  38. prog = Math.round(transferred/(transferred + 200000)*100);
  39. if (prog != prevProg && callback)
  40. callback(prog);
  41. prevProg = prog;
  42. if (abort && abort()) {
  43. errMes = 'abort';
  44. res.request.abort();
  45. }
  46. });
  47. return await download;
  48. } catch (error) {
  49. errMes = (errMes ? errMes : error.message);
  50. throw new Error(errMes);
  51. }
  52. }
  53. async head(url) {
  54. const options = {
  55. headers: {
  56. 'user-agent': userAgent
  57. },
  58. };
  59. const res = await axios.head(url, options);
  60. return res.headers;
  61. }
  62. streamToBuffer(stream, progress) {
  63. return new Promise((resolve, reject) => {
  64. if (!progress)
  65. progress = () => {};
  66. const _buf = [];
  67. stream.on('data', (chunk) => {
  68. _buf.push(chunk);
  69. progress(chunk);
  70. });
  71. stream.on('end', () => resolve(Buffer.concat(_buf)));
  72. stream.on('error', (err) => {
  73. reject(err);
  74. });
  75. stream.on('aborted', () => {
  76. reject(new Error('aborted'));
  77. });
  78. });
  79. }
  80. }
  81. module.exports = FileDownloader;