FileDownloader.js 2.6 KB

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