{"id":106308,"date":"2025-04-16T18:04:50","date_gmt":"2025-04-16T13:34:50","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/"},"modified":"2025-04-16T18:04:50","modified_gmt":"2025-04-16T13:34:50","slug":"building-a-production-ready-file-download-system-with-goframe-55c7","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/","title":{"rendered":"\u0633\u0627\u062e\u062a \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 Goframe"},"content":{"rendered":"<div data-article-id=\"2175137\" id=\"article-body\">\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"\u062a\u063a\u06cc\u06cc\u0631 \u0648\u0636\u0639\u06cc\u062a \u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%85%D9%82%D8%AF%D9%85%D9%87\" >\u0645\u0642\u062f\u0645\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A2%D9%86%DA%86%D9%87_%D9%85%D8%A7_%D9%BE%D9%88%D8%B4%D8%B4_%D8%AE%D9%88%D8%A7%D9%87%DB%8C%D9%85_%D8%AF%D8%A7%D8%AF\" >\u0622\u0646\u0686\u0647 \u0645\u0627 \u067e\u0648\u0634\u0634 \u062e\u0648\u0627\u0647\u06cc\u0645 \u062f\u0627\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%DA%86%D8%B1%D8%A7_Goframe_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%81%D8%A7%DB%8C%D9%84%D8%9F_%F0%9F%A4%94\" >\u0686\u0631\u0627 Goframe \u0628\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644\u061f \ud83e\udd14<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%B4%D8%B1%D9%88%D8%B9_%DA%A9%D8%A7%D8%B1\" >\u0634\u0631\u0648\u0639 \u06a9\u0627\u0631<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%A7%D8%B5%D9%84%DB%8C\" >\u0627\u062c\u0631\u0627\u06cc \u0627\u0635\u0644\u06cc<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A7%D9%85%D9%86%DB%8C%D8%AA_%D8%A7%D9%88%D9%84_%F0%9F%94%92\" >\u0627\u0645\u0646\u06cc\u062a \u0627\u0648\u0644! \ud83d\udd12<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%AF%D8%B3%D8%AA_%D8%B2%D8%AF%D9%86_%D8%A8%D9%87_%D9%BE%D8%B1%D9%88%D9%86%D8%AF%D9%87_%D9%87%D8%A7%DB%8C_%D8%A8%D8%B2%D8%B1%DA%AF_%D9%85%D8%A7%D9%86%D9%86%D8%AF_%DB%8C%DA%A9_%D8%AD%D8%B1%D9%81%D9%87_%D8%A7%DB%8C\" >\u062f\u0633\u062a \u0632\u062f\u0646 \u0628\u0647 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u0645\u0627\u0646\u0646\u062f \u06cc\u06a9 \u062d\u0631\u0641\u0647 \u0627\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%B1%D8%B2%D9%88%D9%85%D9%87_%D9%BE%D8%B4%D8%AA%DB%8C%D8%A8%D8%A7%D9%86%DB%8C_%D8%B2%DB%8C%D8%B1%D8%A7_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%87%D8%A7_%DA%AF%D8%A7%D9%87%DB%8C_%D8%A7%D9%88%D9%82%D8%A7%D8%AA_%D8%B4%DA%A9%D8%B3%D8%AA_%D9%85%DB%8C_%D8%AE%D9%88%D8%B1%D9%86%D8%AF\" >\u0631\u0632\u0648\u0645\u0647 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc: \u0632\u06cc\u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0647\u0627 \u06af\u0627\u0647\u06cc \u0627\u0648\u0642\u0627\u062a \u0634\u06a9\u0633\u062a \u0645\u06cc \u062e\u0648\u0631\u0646\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%B3%D9%86%D8%A7%D8%B1%DB%8C%D9%88%D9%87%D8%A7_%D9%88_%D8%B1%D8%A7%D9%87_%D8%AD%D9%84_%D9%87%D8%A7%DB%8C_%D8%AF%D9%86%DB%8C%D8%A7%DB%8C_%D9%88%D8%A7%D9%82%D8%B9%DB%8C\" >\u0633\u0646\u0627\u0631\u06cc\u0648\u0647\u0627 \u0648 \u0631\u0627\u0647 \u062d\u0644 \u0647\u0627\u06cc \u062f\u0646\u06cc\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#1_%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%A8%D9%87_%D8%A7%D9%86%D9%88%D8%A7%D8%B9_%D9%85%D8%AE%D8%AA%D9%84%D9%81_%D9%81%D8%A7%DB%8C%D9%84\" >1. \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641 \u0641\u0627\u06cc\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#2_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%A7%D8%B2_%D8%B3%D8%A7%D8%B2%DA%AF%D8%A7%D8%B1%DB%8C_%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1\" >2. \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u0645\u0631\u0648\u0631\u06af\u0631<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#3_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%86%D8%B8%D8%A7%D8%B1%D8%AA_%D8%A8%D8%B1_%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA\" >3. \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0646\u0638\u0627\u0631\u062a \u0628\u0631 \u067e\u06cc\u0634\u0631\u0641\u062a<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%86%DA%A9%D8%A7%D8%AA_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%88_%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86_%D8%B4%DB%8C%D9%88%D9%87_%D9%87%D8%A7\" >\u0646\u06a9\u0627\u062a \u062a\u0648\u0644\u06cc\u062f \u0648 \u0628\u0647\u062a\u0631\u06cc\u0646 \u0634\u06cc\u0648\u0647 \u0647\u0627<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%88%DB%8C%DA%98%DA%AF%DB%8C_%D9%87%D8%A7_%D9%88_%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%87%D8%A7%DB%8C_%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87\" >\u0648\u06cc\u0698\u06af\u06cc \u0647\u0627 \u0648 \u0646\u0645\u0648\u0646\u0647 \u0647\u0627\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a\u0647<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#1_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D8%B2%DB%8C%D9%BE_%D8%AF%D8%B1_%D9%BE%D8%B1%D9%88%D8%A7%D8%B2\" >1. \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0632\u06cc\u067e \u062f\u0631 \u067e\u0631\u0648\u0627\u0632<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#2_%D8%A7%D8%AF%D8%BA%D8%A7%D9%85_%D8%B0%D8%AE%DB%8C%D8%B1%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%D8%A7%D8%A8%D8%B1%DB%8C_%F0%9F%8C%A5\" >2. \u0627\u062f\u063a\u0627\u0645 \u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06cc \u0627\u0628\u0631\u06cc \ud83c\udf25<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#3_%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%B5%D9%81_%D8%B1%D8%A7_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%DA%A9%D9%86%DB%8C%D8%AF\" >3. \u0627\u062c\u0631\u0627\u06cc \u0635\u0641 \u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u06a9\u0646\u06cc\u062f<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C_%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%AE%D8%B7%D8%A7%DB%8C_%D8%AC%D8%A7%D9%85%D8%B9\" >\u0627\u0644\u06af\u0648\u0647\u0627\u06cc \u0631\u0633\u06cc\u062f\u06af\u06cc \u062e\u0637\u0627\u06cc \u062c\u0627\u0645\u0639<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%87%D8%A7%DB%8C_%D9%85%D9%88%D8%B1%D8%AF_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%AE%D8%A7%D8%B5\" >\u0646\u0645\u0648\u0646\u0647 \u0647\u0627\u06cc \u0645\u0648\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u062e\u0627\u0635<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#1_%D9%BE%D8%AE%D8%B4_%D9%88%DB%8C%D8%AF%DB%8C%D9%88_%D8%A8%D8%A7_%D9%BE%D8%B4%D8%AA%DB%8C%D8%A8%D8%A7%D9%86%DB%8C_HLS\" >1. \u067e\u062e\u0634 \u0648\u06cc\u062f\u06cc\u0648 \u0628\u0627 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc HLS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#2_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%BE%D8%B1%D9%88%D9%86%D8%AF%D9%87_%D8%A8%D8%B2%D8%B1%DA%AF_%D8%A7%DA%A9%D8%B3%D9%84\" >2. \u062a\u0648\u0644\u06cc\u062f \u067e\u0631\u0648\u0646\u062f\u0647 \u0628\u0632\u0631\u06af \u0627\u06a9\u0633\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#3_PDF_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%88_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C\" >3. PDF \u062a\u0648\u0644\u06cc\u062f \u0648 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#GOTCHA_%D9%87%D8%A7%DB%8C_%D9%85%D8%B4%D8%AA%D8%B1%DA%A9_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%AC%D9%84%D9%88%DA%AF%DB%8C%D8%B1%DB%8C_%D8%A7%D8%B2\" >GOTCHA \u0647\u0627\u06cc \u0645\u0634\u062a\u0631\u06a9 \u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%85%D8%AB%D8%A7%D9%84_%D8%AF%D8%B1_%D8%AF%D9%86%DB%8C%D8%A7%DB%8C_%D9%88%D8%A7%D9%82%D8%B9%DB%8C_%DB%8C%DA%A9_%D8%B3%D8%B1%D9%88%DB%8C%D8%B3_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%DA%A9%D8%A7%D9%85%D9%84\" >\u0645\u062b\u0627\u0644 \u062f\u0631 \u062f\u0646\u06cc\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc: \u06cc\u06a9 \u0633\u0631\u0648\u06cc\u0633 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u06a9\u0627\u0645\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A2%D8%B2%D9%85%D8%A7%DB%8C%D8%B4_%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%AE%D9%88%D8%AF\" >\u0622\u0632\u0645\u0627\u06cc\u0634 \u0627\u062c\u0631\u0627\u06cc \u062e\u0648\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D8%A8%D8%B3%D8%AA%D9%87_%D8%A8%D9%86%D8%AF%DB%8C\" >\u0628\u0633\u062a\u0647 \u0628\u0646\u062f\u06cc<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-27\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%DA%86%D9%87_%DA%86%DB%8C%D8%B2%DB%8C_%D8%A8%D8%B9%D8%AF%DB%8C%D8%9F\" >\u0686\u0647 \u0686\u06cc\u0632\u06cc \u0628\u0639\u062f\u06cc\u061f<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-28\" href=\"https:\/\/nabfollower.com\/blog\/building-a-production-ready-file-download-system-with-goframe-55c7\/#%D9%85%D9%86%D8%A7%D8%A8%D8%B9\" >\u0645\u0646\u0627\u0628\u0639<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D9%82%D8%AF%D9%85%D9%87\"><\/span>\n<p>  \u0645\u0642\u062f\u0645\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0633\u0644\u0627\u0645 devs! \u0627\u06af\u0631 \u062f\u0631 \u062d\u0627\u0644 \u0633\u0627\u062e\u062a \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627\u06cc \u0648\u0628 \u0628\u0627 GO \u0647\u0633\u062a\u06cc\u062f \u060c \u0627\u062d\u062a\u0645\u0627\u0644\u0627\u064b \u0628\u0627 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0631\u0648\u0628\u0631\u0648 \u0634\u062f\u0647 \u0627\u06cc\u062f. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u062f\u0631 \u0627\u0628\u062a\u062f\u0627 \u0633\u0627\u062f\u0647 \u0628\u0647 \u0646\u0638\u0631 \u0628\u0631\u0633\u062f \u060c \u0627\u062c\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 \u0645\u062c\u0645\u0648\u0639\u0647 \u0686\u0627\u0644\u0634 \u0647\u0627\u06cc \u062e\u0627\u0635 \u062e\u0648\u062f \u0647\u0645\u0631\u0627\u0647 \u0627\u0633\u062a. \u062f\u0631 \u0627\u06cc\u0646 \u0631\u0627\u0647\u0646\u0645\u0627 \u060c \u0645\u0646 \u0628\u06cc\u0646\u0634 \u0647\u0627\u06cc \u0639\u0645\u0644\u06cc \u0631\u0627 \u062f\u0631 \u0645\u0648\u0631\u062f \u0633\u0627\u062e\u062a \u0642\u0627\u0628\u0644\u06cc\u062a \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0642\u0648\u06cc \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 goframe \u0628\u0647 \u0627\u0634\u062a\u0631\u0627\u06a9 \u0645\u06cc \u06af\u0630\u0627\u0631\u0645.<\/p>\n<blockquote>\n<p>TL \u061b DR: \u0645\u0627 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0631\u0627 \u0627\u0632 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0627\u0633\u0627\u0633\u06cc \u06af\u0631\u0641\u062a\u0647 \u062a\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0647\u0627\u06cc \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 Goframe \u060c \u0627\u0632 \u062c\u0645\u0644\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u060c \u0627\u062c\u0631\u0627\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0631\u0632\u0648\u0645\u0647 \u0648 \u0628\u0647\u06cc\u0646\u0647 \u0633\u0627\u0632\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u060c \u067e\u0648\u0634\u0634 \u062e\u0648\u0627\u0647\u06cc\u0645 \u062f\u0627\u062f.<\/p>\n<\/blockquote>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A2%D9%86%DA%86%D9%87_%D9%85%D8%A7_%D9%BE%D9%88%D8%B4%D8%B4_%D8%AE%D9%88%D8%A7%D9%87%DB%8C%D9%85_%D8%AF%D8%A7%D8%AF\"><\/span>\n<p>  \u0622\u0646\u0686\u0647 \u0645\u0627 \u067e\u0648\u0634\u0634 \u062e\u0648\u0627\u0647\u06cc\u0645 \u062f\u0627\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>\u062a\u0646\u0638\u06cc\u0645 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0627\u0633\u0627\u0633\u06cc<\/li>\n<li>\u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u0628\u062f\u0648\u0646 \u0645\u0634\u06a9\u0644\u0627\u062a \u062d\u0627\u0641\u0638\u0647<\/li>\n<li>\u0627\u062c\u0631\u0627\u06cc \u0631\u0632\u0648\u0645\u0647\/\u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u062c\u0632\u0626\u06cc<\/li>\n<li>\u0627\u0641\u0632\u0648\u062f\u0646 \u0627\u0642\u062f\u0627\u0645\u0627\u062a \u0627\u0645\u0646\u06cc\u062a\u06cc<\/li>\n<li>\u0628\u0647\u06cc\u0646\u0647 \u0633\u0627\u0632\u06cc \u0628\u0631\u0627\u06cc \u062a\u0648\u0644\u06cc\u062f<\/li>\n<li>\u0646\u0645\u0648\u0646\u0647 \u0647\u0627\u06cc \u062f\u0646\u06cc\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc \u0648 Gotchas<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%DA%86%D8%B1%D8%A7_Goframe_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%81%D8%A7%DB%8C%D9%84%D8%9F_%F0%9F%A4%94\"><\/span>\n<p>  \u0686\u0631\u0627 Goframe \u0628\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644\u061f \ud83e\udd14<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0642\u0628\u0644 \u0627\u0632 \u0634\u06cc\u0631\u062c\u0647 \u0631\u0641\u062a\u0646 \u060c \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u062a\u0639\u062c\u0628 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0686\u0631\u0627 Goframe \u0631\u0627 \u0628\u0631\u0627\u06cc \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u0646\u06cc\u062f. \u0627\u06cc\u0646 \u0645\u0639\u0627\u0645\u0644\u0647 \u0627\u0633\u062a: \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0631\u0627 \u0628\u0627 \u06a9\u062a\u0627\u0628\u062e\u0627\u0646\u0647 \u0647\u0627\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f GO \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u062f \u060c Goframe \u0628\u0631\u062e\u06cc \u0627\u0632 \u0627\u0646\u062a\u0632\u0627\u0639 \u0647\u0627\u06cc \u062e\u0648\u0628 \u0631\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f \u06a9\u0647 \u0632\u0646\u062f\u06af\u06cc \u0645\u0627 \u0631\u0627 \u0622\u0633\u0627\u0646 \u062a\u0631 \u0645\u06cc \u06a9\u0646\u062f:<\/p>\n<ul>\n<li>\u067e\u0631\u062f\u0627\u0632\u0634 \u0645\u0628\u062a\u0646\u06cc \u0628\u0631 \u062c\u0631\u06cc\u0627\u0646 (\u0645\u0634\u06a9\u0644\u0627\u062a \u062d\u0627\u0641\u0638\u0647 \u062e\u062f\u0627\u062d\u0627\u0641\u0638!)<\/li>\n<li>\u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u062f\u0627\u062e\u0644\u06cc \u062f\u0627\u062e\u0644\u06cc<\/li>\n<li>\u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u062e\u0637\u0627\u06cc \u062a\u0645\u06cc\u0632<\/li>\n<li>\u0642\u0627\u0628\u0644\u06cc\u062a \u0647\u0627\u06cc \u0631\u062f\u06cc\u0627\u0628\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B4%D8%B1%D9%88%D8%B9_%DA%A9%D8%A7%D8%B1\"><\/span>\n<p>  \u0634\u0631\u0648\u0639 \u06a9\u0627\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u0648\u0644 \u0686\u06cc\u0632\u0647\u0627 \u0627\u0628\u062a\u062f\u0627 \u060c \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0645\u062d\u06cc\u0637 \u062e\u0648\u062f \u0631\u0627 \u062a\u0646\u0638\u06cc\u0645 \u06a9\u0646\u06cc\u0645. \u0627\u0637\u0645\u06cc\u0646\u0627\u0646 \u062d\u0627\u0635\u0644 \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0646\u0635\u0628 \u0634\u062f\u0647 \u0627\u06cc\u062f (1.16+) \u060c \u0633\u067e\u0633 Goframe \u0631\u0627 \u0628\u06af\u06cc\u0631\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>go get <span class=\"nt\">-u<\/span> github.com\/gogf\/gf\/v2@latest\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%A7%D8%B5%D9%84%DB%8C\"><\/span>\n<p>  \u0627\u062c\u0631\u0627\u06cc \u0627\u0635\u0644\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u06cc\u06a9 \u06a9\u0646\u062a\u0631\u0644 \u06a9\u0646\u0646\u062f\u0647 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0633\u0627\u062f\u0647 \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u0645. \u0627\u06cc\u0646 \u0646\u0642\u0637\u0647 \u0648\u0631\u0648\u062f \u0634\u0645\u0627 \u0628\u0631\u0627\u06cc \u062f\u0631\u06a9 \u0686\u06af\u0648\u0646\u06af\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc Goframe \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">package<\/span> <span class=\"n\">handler<\/span>\n\n<span class=\"k\">import<\/span> <span class=\"p\">(<\/span>\n    <span class=\"s\">\"github.com\/gogf\/gf\/v2\/net\/ghttp\"<\/span>\n<span class=\"p\">)<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">SimpleDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">filePath<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Quick security check<\/span>\n    <span class=\"k\">if<\/span> <span class=\"o\">!<\/span><span class=\"n\">isValidFile<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">403<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Set headers and serve<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/octet-stream\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">ServeFileDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p>\u062e\u06cc\u0644\u06cc \u0633\u0627\u062f\u0647 \u060c \u062f\u0631\u0633\u062a \u0627\u0633\u062a\u061f \u0627\u0645\u0627 \u0635\u0628\u0631 \u06a9\u0646\u06cc\u062f &#8211; \u062f\u0631 \u0647\u0646\u06af\u0627\u0645 \u0633\u0627\u062e\u062a \u0628\u0631\u0627\u06cc \u062a\u0648\u0644\u06cc\u062f \u0628\u06cc\u0634\u062a\u0631 \u0628\u0627\u06cc\u062f \u062f\u0631 \u0646\u0638\u0631 \u0628\u06af\u06cc\u0631\u06cc\u062f! \ud83d\udee0<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D9%85%D9%86%DB%8C%D8%AA_%D8%A7%D9%88%D9%84_%F0%9F%94%92\"><\/span>\n<p>  \u0627\u0645\u0646\u06cc\u062a \u0627\u0648\u0644! \ud83d\udd12<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0642\u0628\u0644 \u0627\u0632 \u0627\u06cc\u0646\u06a9\u0647 \u0627\u0632 \u062e\u062f\u0645\u062a \u0628\u0647 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627 \u062e\u06cc\u0644\u06cc \u0647\u06cc\u062c\u0627\u0646 \u0632\u062f\u0647 \u0634\u0648\u06cc\u0645 \u060c \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u0645\u0646\u06cc\u062a \u0635\u062d\u0628\u062a \u06a9\u0646\u06cc\u0645. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0639\u0645\u0644\u06a9\u0631\u062f \u0627\u0639\u062a\u0628\u0627\u0631 \u0633\u0646\u062c\u06cc \u0642\u0648\u06cc \u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0645\u0633\u0627\u0626\u0644 \u0627\u0645\u0646\u06cc\u062a\u06cc \u0645\u0634\u062a\u0631\u06a9 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">var<\/span> <span class=\"n\">allowedExtensions<\/span> <span class=\"o\">=<\/span> <span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"kt\">bool<\/span><span class=\"p\">{<\/span>\n    <span class=\"s\">\".txt\"<\/span><span class=\"o\">:<\/span>  <span class=\"no\">true<\/span><span class=\"p\">,<\/span>\n    <span class=\"s\">\".pdf\"<\/span><span class=\"o\">:<\/span>  <span class=\"no\">true<\/span><span class=\"p\">,<\/span>\n    <span class=\"s\">\".doc\"<\/span><span class=\"o\">:<\/span>  <span class=\"no\">true<\/span><span class=\"p\">,<\/span>\n    <span class=\"s\">\".xlsx\"<\/span><span class=\"o\">:<\/span> <span class=\"no\">true<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">isValidFile<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">bool<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c\">\/\/ \ud83d\udeab Path traversal check<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">Contains<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"..\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"no\">false<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ \ud83d\udcc1 File existence &amp; type check<\/span>\n    <span class=\"n\">fileInfo<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Stat<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"n\">fileInfo<\/span><span class=\"o\">.<\/span><span class=\"n\">Mode<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">IsRegular<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"no\">false<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ \ud83d\udccf Size check (100MB limit)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">fileInfo<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">()<\/span> <span class=\"o\">&gt;<\/span> <span class=\"m\">100<\/span><span class=\"o\">*<\/span><span class=\"m\">1024<\/span><span class=\"o\">*<\/span><span class=\"m\">1024<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"no\">false<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ \ud83d\udd0d Extension check<\/span>\n    <span class=\"n\">ext<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">ToLower<\/span><span class=\"p\">(<\/span><span class=\"n\">filepath<\/span><span class=\"o\">.<\/span><span class=\"n\">Ext<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">))<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">allowedExtensions<\/span><span class=\"p\">[<\/span><span class=\"n\">ext<\/span><span class=\"p\">]<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AF%D8%B3%D8%AA_%D8%B2%D8%AF%D9%86_%D8%A8%D9%87_%D9%BE%D8%B1%D9%88%D9%86%D8%AF%D9%87_%D9%87%D8%A7%DB%8C_%D8%A8%D8%B2%D8%B1%DA%AF_%D9%85%D8%A7%D9%86%D9%86%D8%AF_%DB%8C%DA%A9_%D8%AD%D8%B1%D9%81%D9%87_%D8%A7%DB%8C\"><\/span>\n<p>  \u062f\u0633\u062a \u0632\u062f\u0646 \u0628\u0647 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u0645\u0627\u0646\u0646\u062f \u06cc\u06a9 \u062d\u0631\u0641\u0647 \u0627\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06a9\u0646\u0648\u0646 \u060c \u0627\u06cc\u0646\u062c\u0627\u0633\u062a \u06a9\u0647 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u062c\u0627\u0644\u0628 \u0645\u06cc \u0634\u0648\u062f. \u0647\u0646\u06af\u0627\u0645 \u0628\u0631\u062e\u0648\u0631\u062f \u0628\u0627 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af \u060c \u0646\u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u062f \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0631\u0627 \u062f\u0631 \u062d\u0627\u0641\u0638\u0647 \u0628\u0627\u0631\u06af\u0630\u0627\u0631\u06cc \u06a9\u0646\u06cc\u062f. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0627\u062c\u0631\u0627\u06cc \u062c\u0631\u06cc\u0627\u0646 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f \u06a9\u0647 \u0628\u0627\u0639\u062b \u0645\u06cc \u0634\u0648\u062f \u0633\u0631\u0648\u0631 \u0634\u0645\u0627 \u06af\u0631\u06cc\u0647 \u06a9\u0646\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">StreamDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">const<\/span> <span class=\"n\">bufSize<\/span> <span class=\"o\">=<\/span> <span class=\"m\">32<\/span> <span class=\"o\">*<\/span> <span class=\"m\">1024<\/span> <span class=\"c\">\/\/ 32KB chunks<\/span>\n\n    <span class=\"n\">file<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">fd<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Open<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">fd<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span> <span class=\"c\">\/\/ Don't forget this! \ud83d\ude09<\/span>\n\n    <span class=\"n\">info<\/span><span class=\"p\">,<\/span> <span class=\"n\">_<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">fd<\/span><span class=\"o\">.<\/span><span class=\"n\">Stat<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Length\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">gconv<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">(<\/span><span class=\"n\">info<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">()))<\/span>\n\n    <span class=\"c\">\/\/ Stream in chunks<\/span>\n    <span class=\"n\">buf<\/span> <span class=\"o\">:=<\/span> <span class=\"nb\">make<\/span><span class=\"p\">([]<\/span><span class=\"kt\">byte<\/span><span class=\"p\">,<\/span> <span class=\"n\">bufSize<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">for<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">n<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">fd<\/span><span class=\"o\">.<\/span><span class=\"n\">Read<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">n<\/span> <span class=\"o\">&gt;<\/span> <span class=\"m\">0<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Write<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">[<\/span><span class=\"o\">:<\/span><span class=\"n\">n<\/span><span class=\"p\">])<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">==<\/span> <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">EOF<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">break<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B1%D8%B2%D9%88%D9%85%D9%87_%D9%BE%D8%B4%D8%AA%DB%8C%D8%A8%D8%A7%D9%86%DB%8C_%D8%B2%DB%8C%D8%B1%D8%A7_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%87%D8%A7_%DA%AF%D8%A7%D9%87%DB%8C_%D8%A7%D9%88%D9%82%D8%A7%D8%AA_%D8%B4%DA%A9%D8%B3%D8%AA_%D9%85%DB%8C_%D8%AE%D9%88%D8%B1%D9%86%D8%AF\"><\/span>\n<p>  \u0631\u0632\u0648\u0645\u0647 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc: \u0632\u06cc\u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0647\u0627 \u06af\u0627\u0647\u06cc \u0627\u0648\u0642\u0627\u062a \u0634\u06a9\u0633\u062a \u0645\u06cc \u062e\u0648\u0631\u0646\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0648\u0627\u0642\u0639\u06cc \u0628\u0627\u0634\u06cc\u0645 &#8211; \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0647\u0627 \u0645\u06cc \u062a\u0648\u0627\u0646\u0646\u062f \u0634\u06a9\u0633\u062a \u0628\u062e\u0648\u0631\u0646\u062f \u060c \u0628\u0647 \u062e\u0635\u0648\u0635 \u0628\u0631\u0627\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0628\u0632\u0631\u06af. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0627\u062c\u0631\u0627\u06cc \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0631\u0632\u0648\u0645\u0647 \u0627\u0631\u0627\u0626\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">ResumeDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">rangeHeader<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Range\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">rangeHeader<\/span> <span class=\"o\">!=<\/span> <span class=\"s\">\"\"<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ Handle range request<\/span>\n        <span class=\"c\">\/\/ ... (previous range parsing code)<\/span>\n\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Range\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"bytes %d-%d\/%d\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">start<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span><span class=\"p\">,<\/span> <span class=\"n\">fileSize<\/span><span class=\"p\">))<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">206<\/span><span class=\"p\">)<\/span> <span class=\"c\">\/\/ Partial Content<\/span>\n\n        <span class=\"c\">\/\/ Serve the requested chunk<\/span>\n        <span class=\"n\">streamFileContent<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">fd<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span><span class=\"o\">-<\/span><span class=\"n\">start<\/span><span class=\"o\">+<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B3%D9%86%D8%A7%D8%B1%DB%8C%D9%88%D9%87%D8%A7_%D9%88_%D8%B1%D8%A7%D9%87_%D8%AD%D9%84_%D9%87%D8%A7%DB%8C_%D8%AF%D9%86%DB%8C%D8%A7%DB%8C_%D9%88%D8%A7%D9%82%D8%B9%DB%8C\"><\/span>\n<p>  \u0633\u0646\u0627\u0631\u06cc\u0648\u0647\u0627 \u0648 \u0631\u0627\u0647 \u062d\u0644 \u0647\u0627\u06cc \u062f\u0646\u06cc\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0647 \u0628\u0631\u062e\u06cc \u0627\u0632 \u0633\u0646\u0627\u0631\u06cc\u0648\u0647\u0627\u06cc \u0645\u062a\u062f\u0627\u0648\u0644 \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u0628\u0627 \u0622\u0646\u0647\u0627 \u0631\u0648\u0628\u0631\u0648 \u0634\u0648\u06cc\u062f \u0648 \u0646\u062d\u0648\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0622\u0646\u0647\u0627 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u0645:<\/p>\n<h3><span class=\"ez-toc-section\" id=\"1_%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%A8%D9%87_%D8%A7%D9%86%D9%88%D8%A7%D8%B9_%D9%85%D8%AE%D8%AA%D9%84%D9%81_%D9%81%D8%A7%DB%8C%D9%84\"><\/span>\n<p>  1. \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641 \u0641\u0627\u06cc\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0627\u0646\u0648\u0627\u0639 \u0645\u062e\u062a\u0644\u0641 \u0641\u0627\u06cc\u0644 \u0647\u0627 \u0627\u063a\u0644\u0628 \u0628\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0645\u062a\u0641\u0627\u0648\u062a\u06cc \u0646\u06cc\u0627\u0632 \u062f\u0627\u0631\u0646\u062f. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0645\u062b\u0627\u0644 \u0639\u0645\u0644\u06cc \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">SmartDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">filePath<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">fileExt<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">ToLower<\/span><span class=\"p\">(<\/span><span class=\"n\">filepath<\/span><span class=\"o\">.<\/span><span class=\"n\">Ext<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"k\">switch<\/span> <span class=\"n\">fileExt<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">case<\/span> <span class=\"s\">\".pdf\"<\/span><span class=\"o\">:<\/span>\n        <span class=\"c\">\/\/ For PDFs, we might want to allow preview<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/pdf\"<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"inline\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">case<\/span> <span class=\"s\">\".csv\"<\/span><span class=\"o\">:<\/span>\n        <span class=\"c\">\/\/ For CSVs, we might want to add BOM for Excel compatibility<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"text\/csv\"<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Write<\/span><span class=\"p\">(<\/span><span class=\"s\">\"<\/span><span class=\"se\">\\xEF\\xBB\\xBF<\/span><span class=\"s\">\"<\/span><span class=\"p\">)<\/span> <span class=\"c\">\/\/ Add BOM<\/span>\n    <span class=\"k\">case<\/span> <span class=\"s\">\".mp4\"<\/span><span class=\"o\">:<\/span>\n        <span class=\"c\">\/\/ For videos, support range requests for streaming<\/span>\n        <span class=\"n\">handleVideoStream<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">default<\/span><span class=\"o\">:<\/span>\n        <span class=\"c\">\/\/ Default download behavior<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/octet-stream\"<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"attachment\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">ServeFileDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">filePath<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"2_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%A7%D8%B2_%D8%B3%D8%A7%D8%B2%DA%AF%D8%A7%D8%B1%DB%8C_%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1\"><\/span>\n<p>  2. \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0633\u0627\u0632\u06af\u0627\u0631\u06cc \u0645\u0631\u0648\u0631\u06af\u0631<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0645\u0631\u0648\u0631\u06af\u0631\u0647\u0627\u06cc \u0645\u062e\u062a\u0644\u0641 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0647\u0627\u06cc \u062f\u06cc\u06af\u0631\u06cc \u0631\u0627 \u0627\u0646\u062c\u0627\u0645 \u0645\u06cc \u062f\u0647\u0646\u062f. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0622\u0646 \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">BrowserAwareDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">filename<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">userAgent<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"User-Agent\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Handle filename encoding for different browsers<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">Contains<\/span><span class=\"p\">(<\/span><span class=\"n\">userAgent<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"MSIE\"<\/span><span class=\"p\">)<\/span> <span class=\"o\">||<\/span> \n       <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">Contains<\/span><span class=\"p\">(<\/span><span class=\"n\">userAgent<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Edge\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ URL encode for IE\/Edge<\/span>\n        <span class=\"n\">filename<\/span> <span class=\"o\">=<\/span> <span class=\"n\">url<\/span><span class=\"o\">.<\/span><span class=\"n\">QueryEscape<\/span><span class=\"p\">(<\/span><span class=\"n\">filename<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ RFC 5987 encoding for others<\/span>\n        <span class=\"n\">filename<\/span> <span class=\"o\">=<\/span> <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"UTF-8''%s\"<\/span><span class=\"p\">,<\/span> \n            <span class=\"n\">url<\/span><span class=\"o\">.<\/span><span class=\"n\">QueryEscape<\/span><span class=\"p\">(<\/span><span class=\"n\">filename<\/span><span class=\"p\">))<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">disposition<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"attachment; filename*=%s\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">filename<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">disposition<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"3_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D9%86%D8%B8%D8%A7%D8%B1%D8%AA_%D8%A8%D8%B1_%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA\"><\/span>\n<p>  3. \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0646\u0638\u0627\u0631\u062a \u0628\u0631 \u067e\u06cc\u0634\u0631\u0641\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0627\u062c\u0631\u0627\u06cc \u0646\u0638\u0627\u0631\u062a \u067e\u06cc\u0634\u0631\u0641\u062a \u0628\u0627 \u0628\u0647 \u0631\u0648\u0632\u0631\u0633\u0627\u0646\u06cc \u0647\u0627\u06cc WebSocket \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">Progress<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Total<\/span>     <span class=\"kt\">int64<\/span>   <span class=\"s\">`json:\"total\"`<\/span>\n    <span class=\"n\">Current<\/span>   <span class=\"kt\">int64<\/span>   <span class=\"s\">`json:\"current\"`<\/span>\n    <span class=\"n\">Speed<\/span>     <span class=\"kt\">float64<\/span> <span class=\"s\">`json:\"speed\"`<\/span>\n    <span class=\"n\">Remaining<\/span> <span class=\"kt\">int<\/span>     <span class=\"s\">`json:\"remaining\"`<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">ProgressDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">ws<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">WebSocket<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">file<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">info<\/span><span class=\"p\">,<\/span> <span class=\"n\">_<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Stat<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">total<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">info<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Create a custom reader that reports progress<\/span>\n    <span class=\"n\">reader<\/span> <span class=\"o\">:=<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">ProgressReader<\/span><span class=\"p\">{<\/span>\n        <span class=\"n\">Reader<\/span><span class=\"o\">:<\/span> <span class=\"n\">bufio<\/span><span class=\"o\">.<\/span><span class=\"n\">NewReader<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">Total<\/span><span class=\"o\">:<\/span>  <span class=\"n\">total<\/span><span class=\"p\">,<\/span>\n        <span class=\"n\">OnProgress<\/span><span class=\"o\">:<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">current<\/span> <span class=\"kt\">int64<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">progress<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">Progress<\/span><span class=\"p\">{<\/span>\n                <span class=\"n\">Total<\/span><span class=\"o\">:<\/span>     <span class=\"n\">total<\/span><span class=\"p\">,<\/span>\n                <span class=\"n\">Current<\/span><span class=\"o\">:<\/span>   <span class=\"n\">current<\/span><span class=\"p\">,<\/span>\n                <span class=\"n\">Speed<\/span><span class=\"o\">:<\/span>    <span class=\"n\">calculateSpeed<\/span><span class=\"p\">(<\/span><span class=\"n\">current<\/span><span class=\"p\">),<\/span>\n                <span class=\"n\">Remaining<\/span><span class=\"o\">:<\/span> <span class=\"n\">calculateRemaining<\/span><span class=\"p\">(<\/span><span class=\"n\">current<\/span><span class=\"p\">,<\/span> <span class=\"n\">total<\/span><span class=\"p\">),<\/span>\n            <span class=\"p\">}<\/span>\n            <span class=\"n\">ws<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJSON<\/span><span class=\"p\">(<\/span><span class=\"n\">progress<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">},<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Copy<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">reader<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%86%DA%A9%D8%A7%D8%AA_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%88_%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86_%D8%B4%DB%8C%D9%88%D9%87_%D9%87%D8%A7\"><\/span>\n<p>  \u0646\u06a9\u0627\u062a \u062a\u0648\u0644\u06cc\u062f \u0648 \u0628\u0647\u062a\u0631\u06cc\u0646 \u0634\u06cc\u0648\u0647 \u0647\u0627<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u067e\u0633 \u0627\u0632 \u0627\u062c\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u062f\u0631 \u0645\u062d\u06cc\u0637 \u0647\u0627\u06cc \u0645\u062a\u0639\u062f\u062f \u062a\u0648\u0644\u06cc\u062f \u060c \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0628\u0631\u062e\u06cc \u0627\u0632 \u0646\u06a9\u0627\u062a \u0622\u0632\u0645\u0627\u06cc\u0634 \u0634\u062f\u0647 \u062a\u0648\u0633\u0637 \u0646\u0628\u0631\u062f \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<p><strong>\u0647\u0645\u06cc\u0634\u0647 \u062d\u062f \u0645\u062c\u0627\u0632<\/strong> \ud83d\udea6<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">var<\/span> <span class=\"n\">downloadLimiter<\/span> <span class=\"o\">=<\/span> <span class=\"n\">rate<\/span><span class=\"o\">.<\/span><span class=\"n\">NewLimiter<\/span><span class=\"p\">(<\/span><span class=\"n\">rate<\/span><span class=\"o\">.<\/span><span class=\"n\">Limit<\/span><span class=\"p\">(<\/span><span class=\"m\">100<\/span><span class=\"p\">),<\/span> <span class=\"m\">200<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><strong>\u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646<\/strong> \ud83d\uddc4<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">CachedDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">data<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">memCache<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">);<\/span> <span class=\"n\">data<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">serveContent<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">data<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"c\">\/\/ ... fallback to disk<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><strong>\u0646\u0638\u0627\u0631\u062a \u0628\u0631 \u0647\u0645\u0647 \u0686\u06cc\u0632<\/strong> \ud83d\udcca<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0627\u062c\u0631\u0627\u06cc \u0646\u0638\u0627\u0631\u062a \u0639\u0645\u0644\u06cc \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">DownloadMetrics<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">ActiveDownloads<\/span>    <span class=\"o\">*<\/span><span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">Int64<\/span>\n    <span class=\"n\">TotalBytes<\/span>        <span class=\"o\">*<\/span><span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">Int64<\/span>\n    <span class=\"n\">ErrorCount<\/span>        <span class=\"o\">*<\/span><span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">Int64<\/span>\n    <span class=\"n\">DownloadDurations<\/span> <span class=\"o\">*<\/span><span class=\"n\">metrics<\/span><span class=\"o\">.<\/span><span class=\"n\">Histogram<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">NewDownloadMetrics<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadMetrics<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">DownloadMetrics<\/span><span class=\"p\">{<\/span>\n        <span class=\"n\">ActiveDownloads<\/span><span class=\"o\">:<\/span>    <span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">NewInt64<\/span><span class=\"p\">(<\/span><span class=\"m\">0<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">TotalBytes<\/span><span class=\"o\">:<\/span>        <span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">NewInt64<\/span><span class=\"p\">(<\/span><span class=\"m\">0<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">ErrorCount<\/span><span class=\"o\">:<\/span>        <span class=\"n\">atomic<\/span><span class=\"o\">.<\/span><span class=\"n\">NewInt64<\/span><span class=\"p\">(<\/span><span class=\"m\">0<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">DownloadDurations<\/span><span class=\"o\">:<\/span> <span class=\"n\">metrics<\/span><span class=\"o\">.<\/span><span class=\"n\">NewHistogram<\/span><span class=\"p\">(<\/span><span class=\"n\">metrics<\/span><span class=\"o\">.<\/span><span class=\"n\">HistogramOpts<\/span><span class=\"p\">{<\/span>\n            <span class=\"n\">Buckets<\/span><span class=\"o\">:<\/span> <span class=\"p\">[]<\/span><span class=\"kt\">float64<\/span><span class=\"p\">{<\/span><span class=\"m\">.1<\/span><span class=\"p\">,<\/span> <span class=\"m\">.5<\/span><span class=\"p\">,<\/span> <span class=\"m\">1<\/span><span class=\"p\">,<\/span> <span class=\"m\">2.5<\/span><span class=\"p\">,<\/span> <span class=\"m\">5<\/span><span class=\"p\">,<\/span> <span class=\"m\">10<\/span><span class=\"p\">,<\/span> <span class=\"m\">30<\/span><span class=\"p\">},<\/span>\n        <span class=\"p\">}),<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">m<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadMetrics<\/span><span class=\"p\">)<\/span> <span class=\"n\">Track<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">start<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Now<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">ActiveDownloads<\/span><span class=\"o\">.<\/span><span class=\"n\">Add<\/span><span class=\"p\">(<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">ActiveDownloads<\/span><span class=\"o\">.<\/span><span class=\"n\">Add<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">duration<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Since<\/span><span class=\"p\">(<\/span><span class=\"n\">start<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">Seconds<\/span><span class=\"p\">()<\/span>\n        <span class=\"n\">m<\/span><span class=\"o\">.<\/span><span class=\"n\">DownloadDurations<\/span><span class=\"o\">.<\/span><span class=\"n\">Observe<\/span><span class=\"p\">(<\/span><span class=\"n\">duration<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><strong>\u0627\u062c\u0631\u0627\u06cc \u0642\u0637\u0639 \u06a9\u0646\u0646\u062f\u0647 \u0645\u062f\u0627\u0631<\/strong> \ud83d\udd0c<\/p>\n<p>\u0627\u0632 \u0633\u06cc\u0633\u062a\u0645 \u062e\u0648\u062f \u0628\u0627 \u0642\u0637\u0639 \u06a9\u0646\u0646\u062f\u0647 \u0645\u062f\u0627\u0631 \u0645\u062d\u0627\u0641\u0638\u062a \u06a9\u0646\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">DownloadBreaker<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">breaker<\/span> <span class=\"o\">*<\/span><span class=\"n\">gobreaker<\/span><span class=\"o\">.<\/span><span class=\"n\">CircuitBreaker<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">NewDownloadBreaker<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadBreaker<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">DownloadBreaker<\/span><span class=\"p\">{<\/span>\n        <span class=\"n\">breaker<\/span><span class=\"o\">:<\/span> <span class=\"n\">gobreaker<\/span><span class=\"o\">.<\/span><span class=\"n\">NewCircuitBreaker<\/span><span class=\"p\">(<\/span><span class=\"n\">gobreaker<\/span><span class=\"o\">.<\/span><span class=\"n\">Settings<\/span><span class=\"p\">{<\/span>\n            <span class=\"n\">Name<\/span><span class=\"o\">:<\/span>        <span class=\"s\">\"download-breaker\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">MaxRequests<\/span><span class=\"o\">:<\/span> <span class=\"m\">100<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">Interval<\/span><span class=\"o\">:<\/span>    <span class=\"m\">10<\/span> <span class=\"o\">*<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Second<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">Timeout<\/span><span class=\"o\">:<\/span>     <span class=\"m\">30<\/span> <span class=\"o\">*<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Second<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">ReadyToTrip<\/span><span class=\"o\">:<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"n\">counts<\/span> <span class=\"n\">gobreaker<\/span><span class=\"o\">.<\/span><span class=\"n\">Counts<\/span><span class=\"p\">)<\/span> <span class=\"kt\">bool<\/span> <span class=\"p\">{<\/span>\n                <span class=\"n\">failureRatio<\/span> <span class=\"o\">:=<\/span> <span class=\"kt\">float64<\/span><span class=\"p\">(<\/span><span class=\"n\">counts<\/span><span class=\"o\">.<\/span><span class=\"n\">TotalFailures<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"kt\">float64<\/span><span class=\"p\">(<\/span><span class=\"n\">counts<\/span><span class=\"o\">.<\/span><span class=\"n\">Requests<\/span><span class=\"p\">)<\/span>\n                <span class=\"k\">return<\/span> <span class=\"n\">counts<\/span><span class=\"o\">.<\/span><span class=\"n\">Requests<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"m\">10<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"n\">failureRatio<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"m\">0.6<\/span>\n            <span class=\"p\">},<\/span>\n        <span class=\"p\">}),<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><strong>\u062e\u0627\u0645\u0648\u0634 \u06a9\u0631\u062f\u0646 \u0628\u0631\u0627\u0632\u0646\u062f\u0647<\/strong> \ud83d\uded1<\/p>\n<p>\u062e\u0627\u0645\u0648\u0634 \u06a9\u0631\u062f\u0646 \u0647\u0627 \u0631\u0627 \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc \u0627\u0646\u062c\u0627\u0645 \u062f\u0647\u06cc\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">DownloadManager<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">activeDownloads<\/span> <span class=\"n\">sync<\/span><span class=\"o\">.<\/span><span class=\"n\">WaitGroup<\/span>\n    <span class=\"n\">shutdownCh<\/span>     <span class=\"k\">chan<\/span> <span class=\"k\">struct<\/span><span class=\"p\">{}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">dm<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadManager<\/span><span class=\"p\">)<\/span> <span class=\"n\">HandleDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">dm<\/span><span class=\"o\">.<\/span><span class=\"n\">activeDownloads<\/span><span class=\"o\">.<\/span><span class=\"n\">Add<\/span><span class=\"p\">(<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">dm<\/span><span class=\"o\">.<\/span><span class=\"n\">activeDownloads<\/span><span class=\"o\">.<\/span><span class=\"n\">Done<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Create download context with shutdown signal<\/span>\n    <span class=\"n\">ctx<\/span><span class=\"p\">,<\/span> <span class=\"n\">cancel<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">context<\/span><span class=\"o\">.<\/span><span class=\"n\">WithCancel<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">())<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">cancel<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"k\">go<\/span> <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">select<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">case<\/span> <span class=\"o\">&lt;-<\/span><span class=\"n\">dm<\/span><span class=\"o\">.<\/span><span class=\"n\">shutdownCh<\/span><span class=\"o\">:<\/span>\n            <span class=\"c\">\/\/ Save progress and cleanup<\/span>\n            <span class=\"n\">cancel<\/span><span class=\"p\">()<\/span>\n        <span class=\"k\">case<\/span> <span class=\"o\">&lt;-<\/span><span class=\"n\">ctx<\/span><span class=\"o\">.<\/span><span class=\"n\">Done<\/span><span class=\"p\">()<\/span><span class=\"o\">:<\/span>\n            <span class=\"k\">return<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}()<\/span>\n\n    <span class=\"c\">\/\/ Proceed with download...<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">dm<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadManager<\/span><span class=\"p\">)<\/span> <span class=\"n\">Shutdown<\/span><span class=\"p\">(<\/span><span class=\"n\">timeout<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nb\">close<\/span><span class=\"p\">(<\/span><span class=\"n\">dm<\/span><span class=\"o\">.<\/span><span class=\"n\">shutdownCh<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Wait for active downloads with timeout<\/span>\n    <span class=\"n\">c<\/span> <span class=\"o\">:=<\/span> <span class=\"nb\">make<\/span><span class=\"p\">(<\/span><span class=\"k\">chan<\/span> <span class=\"k\">struct<\/span><span class=\"p\">{})<\/span>\n    <span class=\"k\">go<\/span> <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">dm<\/span><span class=\"o\">.<\/span><span class=\"n\">activeDownloads<\/span><span class=\"o\">.<\/span><span class=\"n\">Wait<\/span><span class=\"p\">()<\/span>\n        <span class=\"nb\">close<\/span><span class=\"p\">(<\/span><span class=\"n\">c<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}()<\/span>\n\n    <span class=\"k\">select<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">case<\/span> <span class=\"o\">&lt;-<\/span><span class=\"n\">c<\/span><span class=\"o\">:<\/span>\n        <span class=\"k\">return<\/span> <span class=\"no\">nil<\/span>\n    <span class=\"k\">case<\/span> <span class=\"o\">&lt;-<\/span><span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">After<\/span><span class=\"p\">(<\/span><span class=\"n\">timeout<\/span><span class=\"p\">)<\/span><span class=\"o\">:<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">errors<\/span><span class=\"o\">.<\/span><span class=\"n\">New<\/span><span class=\"p\">(<\/span><span class=\"s\">\"shutdown timeout\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%88%DB%8C%DA%98%DA%AF%DB%8C_%D9%87%D8%A7_%D9%88_%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%87%D8%A7%DB%8C_%D9%BE%DB%8C%D8%B4%D8%B1%D9%81%D8%AA%D9%87\"><\/span>\n<p>  \u0648\u06cc\u0698\u06af\u06cc \u0647\u0627 \u0648 \u0646\u0645\u0648\u0646\u0647 \u0647\u0627\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"1_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%D8%B2%DB%8C%D9%BE_%D8%AF%D8%B1_%D9%BE%D8%B1%D9%88%D8%A7%D8%B2\"><\/span>\n<p>  1. \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0632\u06cc\u067e \u062f\u0631 \u067e\u0631\u0648\u0627\u0632<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0622\u06cc\u0627 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0627\u06cc\u062c\u0627\u062f \u0628\u0627\u06cc\u06af\u0627\u0646\u06cc \u0632\u06cc\u067e \u0628\u0647 \u0635\u0648\u0631\u062a \u067e\u0648\u06cc\u0627 \u062f\u0627\u0631\u06cc\u062f\u061f \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0686\u06af\u0648\u0646\u0647:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">ZipDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">files<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">GetArray<\/span><span class=\"p\">(<\/span><span class=\"s\">\"files\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/zip\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> \n        <span class=\"s\">\"attachment; filename=archive.zip\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">zw<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">zip<\/span><span class=\"o\">.<\/span><span class=\"n\">NewWriter<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">zw<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">_<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span> <span class=\"o\">:=<\/span> <span class=\"k\">range<\/span> <span class=\"n\">files<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ Add file to zip<\/span>\n        <span class=\"n\">f<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Open<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">continue<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">defer<\/span> <span class=\"n\">f<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span>\n\n        <span class=\"c\">\/\/ Create zip entry<\/span>\n        <span class=\"n\">header<\/span> <span class=\"o\">:=<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">zip<\/span><span class=\"o\">.<\/span><span class=\"n\">FileHeader<\/span><span class=\"p\">{<\/span>\n            <span class=\"n\">Name<\/span><span class=\"o\">:<\/span>   <span class=\"n\">filepath<\/span><span class=\"o\">.<\/span><span class=\"n\">Base<\/span><span class=\"p\">(<\/span><span class=\"n\">file<\/span><span class=\"p\">),<\/span>\n            <span class=\"n\">Method<\/span><span class=\"o\">:<\/span> <span class=\"n\">zip<\/span><span class=\"o\">.<\/span><span class=\"n\">Deflate<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"n\">writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">zw<\/span><span class=\"o\">.<\/span><span class=\"n\">CreateHeader<\/span><span class=\"p\">(<\/span><span class=\"n\">header<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">continue<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Copy<\/span><span class=\"p\">(<\/span><span class=\"n\">writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">f<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"2_%D8%A7%D8%AF%D8%BA%D8%A7%D9%85_%D8%B0%D8%AE%DB%8C%D8%B1%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%D8%A7%D8%A8%D8%B1%DB%8C_%F0%9F%8C%A5\"><\/span>\n<p>  2. \u0627\u062f\u063a\u0627\u0645 \u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06cc \u0627\u0628\u0631\u06cc \ud83c\udf25<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0645\u062b\u0627\u0644\u06cc \u0628\u0627 \u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06af\u0627\u0631 \u0628\u0627 S3 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">CloudDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">bucket<\/span> <span class=\"o\">:=<\/span> <span class=\"s\">\"my-bucket\"<\/span>\n    <span class=\"n\">key<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"key\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Get object from S3<\/span>\n    <span class=\"n\">input<\/span> <span class=\"o\">:=<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">s3<\/span><span class=\"o\">.<\/span><span class=\"n\">GetObjectInput<\/span><span class=\"p\">{<\/span>\n        <span class=\"n\">Bucket<\/span><span class=\"o\">:<\/span> <span class=\"n\">aws<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">(<\/span><span class=\"n\">bucket<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">Key<\/span><span class=\"o\">:<\/span>    <span class=\"n\">aws<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">(<\/span><span class=\"n\">key<\/span><span class=\"p\">),<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">result<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">s3Client<\/span><span class=\"o\">.<\/span><span class=\"n\">GetObject<\/span><span class=\"p\">(<\/span><span class=\"n\">input<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">result<\/span><span class=\"o\">.<\/span><span class=\"n\">Body<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Set headers<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"o\">*<\/span><span class=\"n\">result<\/span><span class=\"o\">.<\/span><span class=\"n\">ContentType<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Length\"<\/span><span class=\"p\">,<\/span> \n        <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"%d\"<\/span><span class=\"p\">,<\/span> <span class=\"o\">*<\/span><span class=\"n\">result<\/span><span class=\"o\">.<\/span><span class=\"n\">ContentLength<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"c\">\/\/ Stream the response<\/span>\n    <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Copy<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">result<\/span><span class=\"o\">.<\/span><span class=\"n\">Body<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"3_%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%B5%D9%81_%D8%B1%D8%A7_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%DA%A9%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  3. \u0627\u062c\u0631\u0627\u06cc \u0635\u0641 \u0631\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u06a9\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>\u0628\u0631\u0627\u06cc \u0645\u062f\u06cc\u0631\u06cc\u062a \u062a\u0639\u062f\u0627\u062f \u0632\u06cc\u0627\u062f\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">DownloadQueue<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">queue<\/span>    <span class=\"k\">chan<\/span> <span class=\"n\">DownloadJob<\/span>\n    <span class=\"n\">workers<\/span>  <span class=\"kt\">int<\/span>\n    <span class=\"n\">metrics<\/span>  <span class=\"o\">*<\/span><span class=\"n\">DownloadMetrics<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">type<\/span> <span class=\"n\">DownloadJob<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">ID<\/span>       <span class=\"kt\">string<\/span>\n    <span class=\"n\">FilePath<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">Priority<\/span> <span class=\"kt\">int<\/span>\n    <span class=\"n\">Callback<\/span> <span class=\"k\">func<\/span><span class=\"p\">(<\/span><span class=\"kt\">error<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">NewDownloadQueue<\/span><span class=\"p\">(<\/span><span class=\"n\">workers<\/span> <span class=\"kt\">int<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadQueue<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">dq<\/span> <span class=\"o\">:=<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">DownloadQueue<\/span><span class=\"p\">{<\/span>\n        <span class=\"n\">queue<\/span><span class=\"o\">:<\/span>   <span class=\"nb\">make<\/span><span class=\"p\">(<\/span><span class=\"k\">chan<\/span> <span class=\"n\">DownloadJob<\/span><span class=\"p\">,<\/span> <span class=\"m\">1000<\/span><span class=\"p\">),<\/span>\n        <span class=\"n\">workers<\/span><span class=\"o\">:<\/span> <span class=\"n\">workers<\/span><span class=\"p\">,<\/span>\n        <span class=\"n\">metrics<\/span><span class=\"o\">:<\/span> <span class=\"n\">NewDownloadMetrics<\/span><span class=\"p\">(),<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"o\">:=<\/span> <span class=\"m\">0<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">workers<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span><span class=\"o\">++<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">go<\/span> <span class=\"n\">dq<\/span><span class=\"o\">.<\/span><span class=\"n\">worker<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">dq<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">dq<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadQueue<\/span><span class=\"p\">)<\/span> <span class=\"n\">worker<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">job<\/span> <span class=\"o\">:=<\/span> <span class=\"k\">range<\/span> <span class=\"n\">dq<\/span><span class=\"o\">.<\/span><span class=\"n\">queue<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ Process download job<\/span>\n        <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">processDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">job<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">job<\/span><span class=\"o\">.<\/span><span class=\"n\">Callback<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">job<\/span><span class=\"o\">.<\/span><span class=\"n\">Callback<\/span><span class=\"p\">(<\/span><span class=\"n\">err<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">dq<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadQueue<\/span><span class=\"p\">)<\/span> <span class=\"n\">Enqueue<\/span><span class=\"p\">(<\/span><span class=\"n\">job<\/span> <span class=\"n\">DownloadJob<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">select<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">case<\/span> <span class=\"n\">dq<\/span><span class=\"o\">.<\/span><span class=\"n\">queue<\/span> <span class=\"o\">&lt;-<\/span> <span class=\"n\">job<\/span><span class=\"o\">:<\/span>\n        <span class=\"k\">return<\/span> <span class=\"no\">nil<\/span>\n    <span class=\"k\">default<\/span><span class=\"o\">:<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">errors<\/span><span class=\"o\">.<\/span><span class=\"n\">New<\/span><span class=\"p\">(<\/span><span class=\"s\">\"queue full\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C_%D8%B1%D8%B3%DB%8C%D8%AF%DA%AF%DB%8C_%D8%AE%D8%B7%D8%A7%DB%8C_%D8%AC%D8%A7%D9%85%D8%B9\"><\/span>\n<p>  \u0627\u0644\u06af\u0648\u0647\u0627\u06cc \u0631\u0633\u06cc\u062f\u06af\u06cc \u062e\u0637\u0627\u06cc \u062c\u0627\u0645\u0639<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0647 \u0646\u062d\u0648\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0633\u0646\u0627\u0631\u06cc\u0648\u0647\u0627\u06cc \u0645\u062e\u062a\u0644\u0641 \u062e\u0637\u0627\u06cc \u0628\u0627 \u0642\u0627\u0637\u0639\u06cc\u062a \u0628\u067e\u0631\u062f\u0627\u0632\u06cc\u0645:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"c\">\/\/ Custom error types for better error handling<\/span>\n<span class=\"k\">type<\/span> <span class=\"n\">DownloadError<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">Code<\/span>    <span class=\"kt\">int<\/span>\n    <span class=\"n\">Message<\/span> <span class=\"kt\">string<\/span>\n    <span class=\"n\">Err<\/span>     <span class=\"kt\">error<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">e<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadError<\/span><span class=\"p\">)<\/span> <span class=\"n\">Error<\/span><span class=\"p\">()<\/span> <span class=\"kt\">string<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">e<\/span><span class=\"o\">.<\/span><span class=\"n\">Err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"%s: %v\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"o\">.<\/span><span class=\"n\">Message<\/span><span class=\"p\">,<\/span> <span class=\"n\">e<\/span><span class=\"o\">.<\/span><span class=\"n\">Err<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">e<\/span><span class=\"o\">.<\/span><span class=\"n\">Message<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Error codes<\/span>\n<span class=\"k\">const<\/span> <span class=\"p\">(<\/span>\n    <span class=\"n\">ErrFileNotFound<\/span> <span class=\"o\">=<\/span> <span class=\"no\">iota<\/span> <span class=\"o\">+<\/span> <span class=\"m\">1000<\/span>\n    <span class=\"n\">ErrPermissionDenied<\/span>\n    <span class=\"n\">ErrQuotaExceeded<\/span>\n    <span class=\"n\">ErrInvalidFileType<\/span>\n    <span class=\"n\">ErrFileTooLarge<\/span>\n<span class=\"p\">)<\/span>\n\n<span class=\"c\">\/\/ Robust download handler with error handling<\/span>\n<span class=\"k\">func<\/span> <span class=\"n\">RobustDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"k\">func<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"nb\">recover<\/span><span class=\"p\">();<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"c\">\/\/ Log the stack trace<\/span>\n            <span class=\"n\">debug<\/span><span class=\"o\">.<\/span><span class=\"n\">PrintStack<\/span><span class=\"p\">()<\/span>\n            <span class=\"c\">\/\/ Return 500 error to client<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}()<\/span>\n\n    <span class=\"n\">file<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Validate request<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">validateDownloadRequest<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">);<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">handleDownloadError<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Check user quota<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">checkUserQuota<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">);<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">handleDownloadError<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">DownloadError<\/span><span class=\"p\">{<\/span>\n            <span class=\"n\">Code<\/span><span class=\"o\">:<\/span>    <span class=\"n\">ErrQuotaExceeded<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">Message<\/span><span class=\"o\">:<\/span> <span class=\"s\">\"Download quota exceeded\"<\/span><span class=\"p\">,<\/span>\n            <span class=\"n\">Err<\/span><span class=\"o\">:<\/span>     <span class=\"n\">err<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">})<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Attempt file download<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">streamFileWithRetry<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">);<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">handleDownloadError<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Error handler for different scenarios<\/span>\n<span class=\"k\">func<\/span> <span class=\"n\">handleDownloadError<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"kt\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">var<\/span> <span class=\"n\">downloadErr<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadError<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">errors<\/span><span class=\"o\">.<\/span><span class=\"n\">As<\/span><span class=\"p\">(<\/span><span class=\"n\">err<\/span><span class=\"p\">,<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">downloadErr<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">switch<\/span> <span class=\"n\">downloadErr<\/span><span class=\"o\">.<\/span><span class=\"n\">Code<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">case<\/span> <span class=\"n\">ErrFileNotFound<\/span><span class=\"o\">:<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">404<\/span><span class=\"p\">)<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJson<\/span><span class=\"p\">(<\/span><span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Map<\/span><span class=\"p\">{<\/span>\n                <span class=\"s\">\"error\"<\/span><span class=\"o\">:<\/span> <span class=\"s\">\"File not found\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"s\">\"details\"<\/span><span class=\"o\">:<\/span> <span class=\"n\">downloadErr<\/span><span class=\"o\">.<\/span><span class=\"n\">Message<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">})<\/span>\n        <span class=\"k\">case<\/span> <span class=\"n\">ErrPermissionDenied<\/span><span class=\"o\">:<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">403<\/span><span class=\"p\">)<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJson<\/span><span class=\"p\">(<\/span><span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Map<\/span><span class=\"p\">{<\/span>\n                <span class=\"s\">\"error\"<\/span><span class=\"o\">:<\/span> <span class=\"s\">\"Access denied\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"s\">\"details\"<\/span><span class=\"o\">:<\/span> <span class=\"n\">downloadErr<\/span><span class=\"o\">.<\/span><span class=\"n\">Message<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">})<\/span>\n        <span class=\"k\">case<\/span> <span class=\"n\">ErrQuotaExceeded<\/span><span class=\"o\">:<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">429<\/span><span class=\"p\">)<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJson<\/span><span class=\"p\">(<\/span><span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Map<\/span><span class=\"p\">{<\/span>\n                <span class=\"s\">\"error\"<\/span><span class=\"o\">:<\/span> <span class=\"s\">\"Quota exceeded\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"s\">\"details\"<\/span><span class=\"o\">:<\/span> <span class=\"n\">downloadErr<\/span><span class=\"o\">.<\/span><span class=\"n\">Message<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">})<\/span>\n        <span class=\"k\">default<\/span><span class=\"o\">:<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJson<\/span><span class=\"p\">(<\/span><span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Map<\/span><span class=\"p\">{<\/span>\n                <span class=\"s\">\"error\"<\/span><span class=\"o\">:<\/span> <span class=\"s\">\"Internal server error\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"s\">\"reference\"<\/span><span class=\"o\">:<\/span> <span class=\"n\">uuid<\/span><span class=\"o\">.<\/span><span class=\"n\">New<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">(),<\/span>\n            <span class=\"p\">})<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Handle generic errors<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"c\">\/\/ Retry mechanism for transient failures<\/span>\n<span class=\"k\">func<\/span> <span class=\"n\">streamFileWithRetry<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"kt\">error<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">const<\/span> <span class=\"n\">maxRetries<\/span> <span class=\"o\">=<\/span> <span class=\"m\">3<\/span>\n    <span class=\"k\">const<\/span> <span class=\"n\">baseDelay<\/span> <span class=\"o\">=<\/span> <span class=\"m\">100<\/span> <span class=\"o\">*<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Millisecond<\/span>\n\n    <span class=\"k\">var<\/span> <span class=\"n\">lastErr<\/span> <span class=\"kt\">error<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">attempt<\/span> <span class=\"o\">:=<\/span> <span class=\"m\">0<\/span><span class=\"p\">;<\/span> <span class=\"n\">attempt<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">maxRetries<\/span><span class=\"p\">;<\/span> <span class=\"n\">attempt<\/span><span class=\"o\">++<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">streamFile<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">==<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">return<\/span> <span class=\"no\">nil<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"n\">lastErr<\/span> <span class=\"o\">=<\/span> <span class=\"n\">err<\/span>\n\n        <span class=\"c\">\/\/ Don't retry on certain errors<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">errors<\/span><span class=\"o\">.<\/span><span class=\"n\">Is<\/span><span class=\"p\">(<\/span><span class=\"n\">err<\/span><span class=\"p\">,<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">ErrNotExist<\/span><span class=\"p\">)<\/span> <span class=\"o\">||<\/span> \n           <span class=\"n\">errors<\/span><span class=\"o\">.<\/span><span class=\"n\">Is<\/span><span class=\"p\">(<\/span><span class=\"n\">err<\/span><span class=\"p\">,<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">ErrPermission<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">return<\/span> <span class=\"n\">err<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"c\">\/\/ Exponential backoff<\/span>\n        <span class=\"n\">delay<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">baseDelay<\/span> <span class=\"o\">*<\/span> <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Duration<\/span><span class=\"p\">(<\/span><span class=\"n\">math<\/span><span class=\"o\">.<\/span><span class=\"n\">Pow<\/span><span class=\"p\">(<\/span><span class=\"m\">2<\/span><span class=\"p\">,<\/span> <span class=\"kt\">float64<\/span><span class=\"p\">(<\/span><span class=\"n\">attempt<\/span><span class=\"p\">)))<\/span>\n        <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Sleep<\/span><span class=\"p\">(<\/span><span class=\"n\">delay<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Errorf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"failed after %d attempts: %w\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">maxRetries<\/span><span class=\"p\">,<\/span> <span class=\"n\">lastErr<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%86%D9%85%D9%88%D9%86%D9%87_%D9%87%D8%A7%DB%8C_%D9%85%D9%88%D8%B1%D8%AF_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%AE%D8%A7%D8%B5\"><\/span>\n<p>  \u0646\u0645\u0648\u0646\u0647 \u0647\u0627\u06cc \u0645\u0648\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u062e\u0627\u0635<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<h3><span class=\"ez-toc-section\" id=\"1_%D9%BE%D8%AE%D8%B4_%D9%88%DB%8C%D8%AF%DB%8C%D9%88_%D8%A8%D8%A7_%D9%BE%D8%B4%D8%AA%DB%8C%D8%A8%D8%A7%D9%86%DB%8C_HLS\"><\/span>\n<p>  1. \u067e\u062e\u0634 \u0648\u06cc\u062f\u06cc\u0648 \u0628\u0627 \u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc HLS<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">VideoStreamHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">videoPath<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"video\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Check if requesting manifest<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">HasSuffix<\/span><span class=\"p\">(<\/span><span class=\"n\">videoPath<\/span><span class=\"p\">,<\/span> <span class=\"s\">\".m3u8\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">serveHLSManifest<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">videoPath<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Check if requesting segment<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">strings<\/span><span class=\"o\">.<\/span><span class=\"n\">HasSuffix<\/span><span class=\"p\">(<\/span><span class=\"n\">videoPath<\/span><span class=\"p\">,<\/span> <span class=\"s\">\".ts\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">serveHLSSegment<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">videoPath<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Serve video file directly with range support<\/span>\n    <span class=\"n\">serveVideoWithRange<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">videoPath<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">serveHLSManifest<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"n\">path<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/vnd.apple.mpegurl\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Cache-Control\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"max-age=5\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Read and serve manifest<\/span>\n    <span class=\"n\">content<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">ioutil<\/span><span class=\"o\">.<\/span><span class=\"n\">ReadFile<\/span><span class=\"p\">(<\/span><span class=\"n\">path<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">404<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Write<\/span><span class=\"p\">(<\/span><span class=\"n\">content<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">serveVideoWithRange<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"n\">path<\/span> <span class=\"kt\">string<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">info<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Stat<\/span><span class=\"p\">(<\/span><span class=\"n\">path<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">404<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">file<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">os<\/span><span class=\"o\">.<\/span><span class=\"n\">Open<\/span><span class=\"p\">(<\/span><span class=\"n\">path<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"n\">rangeHeader<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Range\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">rangeHeader<\/span> <span class=\"o\">!=<\/span> <span class=\"s\">\"\"<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">ranges<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">parseRange<\/span><span class=\"p\">(<\/span><span class=\"n\">rangeHeader<\/span><span class=\"p\">,<\/span> <span class=\"n\">info<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">())<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">416<\/span><span class=\"p\">)<\/span>\n            <span class=\"k\">return<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"k\">if<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">ranges<\/span><span class=\"p\">)<\/span> <span class=\"o\">&gt;<\/span> <span class=\"m\">0<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">start<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">ranges<\/span><span class=\"p\">[<\/span><span class=\"m\">0<\/span><span class=\"p\">][<\/span><span class=\"m\">0<\/span><span class=\"p\">],<\/span> <span class=\"n\">ranges<\/span><span class=\"p\">[<\/span><span class=\"m\">0<\/span><span class=\"p\">][<\/span><span class=\"m\">1<\/span><span class=\"p\">]<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Range\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"bytes %d-%d\/%d\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">start<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span><span class=\"p\">,<\/span> <span class=\"n\">info<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">()))<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Length\"<\/span><span class=\"p\">,<\/span>\n                <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"%d\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span><span class=\"o\">-<\/span><span class=\"n\">start<\/span><span class=\"o\">+<\/span><span class=\"m\">1<\/span><span class=\"p\">))<\/span>\n            <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">206<\/span><span class=\"p\">)<\/span>\n\n            <span class=\"n\">file<\/span><span class=\"o\">.<\/span><span class=\"n\">Seek<\/span><span class=\"p\">(<\/span><span class=\"n\">start<\/span><span class=\"p\">,<\/span> <span class=\"m\">0<\/span><span class=\"p\">)<\/span>\n            <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">CopyN<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">,<\/span> <span class=\"n\">end<\/span><span class=\"o\">-<\/span><span class=\"n\">start<\/span><span class=\"o\">+<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n            <span class=\"k\">return<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Length\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"%d\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">info<\/span><span class=\"o\">.<\/span><span class=\"n\">Size<\/span><span class=\"p\">()))<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"video\/mp4\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">io<\/span><span class=\"o\">.<\/span><span class=\"n\">Copy<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">,<\/span> <span class=\"n\">file<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"2_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%BE%D8%B1%D9%88%D9%86%D8%AF%D9%87_%D8%A8%D8%B2%D8%B1%DA%AF_%D8%A7%DA%A9%D8%B3%D9%84\"><\/span>\n<p>  2. \u062a\u0648\u0644\u06cc\u062f \u067e\u0631\u0648\u0646\u062f\u0647 \u0628\u0632\u0631\u06af \u0627\u06a9\u0633\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">ExcelDownloadHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c\">\/\/ Create a new file<\/span>\n    <span class=\"n\">f<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">excelize<\/span><span class=\"o\">.<\/span><span class=\"n\">NewFile<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">defer<\/span> <span class=\"n\">f<\/span><span class=\"o\">.<\/span><span class=\"n\">Close<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Create buffered writer<\/span>\n    <span class=\"n\">buf<\/span> <span class=\"o\">:=<\/span> <span class=\"nb\">new<\/span><span class=\"p\">(<\/span><span class=\"n\">bytes<\/span><span class=\"o\">.<\/span><span class=\"n\">Buffer<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">writer<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">bufio<\/span><span class=\"o\">.<\/span><span class=\"n\">NewWriter<\/span><span class=\"p\">(<\/span><span class=\"n\">buf<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Start progress tracking<\/span>\n    <span class=\"n\">progress<\/span> <span class=\"o\">:=<\/span> <span class=\"m\">0<\/span>\n    <span class=\"n\">total<\/span> <span class=\"o\">:=<\/span> <span class=\"m\">1000000<\/span> <span class=\"c\">\/\/ Example: 1 million rows<\/span>\n\n    <span class=\"c\">\/\/ Stream data writing<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"o\">:=<\/span> <span class=\"m\">0<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">total<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span><span class=\"o\">++<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c\">\/\/ Write row data<\/span>\n        <span class=\"n\">row<\/span> <span class=\"o\">:=<\/span> <span class=\"p\">[]<\/span><span class=\"k\">interface<\/span><span class=\"p\">{}{<\/span>\n            <span class=\"n\">fmt<\/span><span class=\"o\">.<\/span><span class=\"n\">Sprintf<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Data %d\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">i<\/span><span class=\"p\">),<\/span>\n            <span class=\"n\">time<\/span><span class=\"o\">.<\/span><span class=\"n\">Now<\/span><span class=\"p\">(),<\/span>\n            <span class=\"n\">rand<\/span><span class=\"o\">.<\/span><span class=\"n\">Float64<\/span><span class=\"p\">(),<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"n\">cell<\/span><span class=\"p\">,<\/span> <span class=\"n\">_<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">excelize<\/span><span class=\"o\">.<\/span><span class=\"n\">CoordinatesToCellName<\/span><span class=\"p\">(<\/span><span class=\"m\">1<\/span><span class=\"p\">,<\/span> <span class=\"n\">i<\/span><span class=\"o\">+<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">f<\/span><span class=\"o\">.<\/span><span class=\"n\">SetSheetRow<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Sheet1\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">cell<\/span><span class=\"p\">,<\/span> <span class=\"o\">&amp;<\/span><span class=\"n\">row<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"c\">\/\/ Update progress every 1%<\/span>\n        <span class=\"n\">currentProgress<\/span> <span class=\"o\">:=<\/span> <span class=\"p\">(<\/span><span class=\"n\">i<\/span> <span class=\"o\">*<\/span> <span class=\"m\">100<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">total<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">currentProgress<\/span> <span class=\"o\">&gt;<\/span> <span class=\"n\">progress<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">progress<\/span> <span class=\"o\">=<\/span> <span class=\"n\">currentProgress<\/span>\n            <span class=\"c\">\/\/ Send progress through WebSocket if needed<\/span>\n            <span class=\"n\">sendProgress<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">progress<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Set headers for Excel file<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> \n        <span class=\"s\">\"application\/vnd.openxmlformats-officedocument.spreadsheetml.sheet\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> \n        <span class=\"s\">\"attachment; filename=large-report.xlsx\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Save to response writer<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">f<\/span><span class=\"o\">.<\/span><span class=\"n\">Write<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">);<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"n\">sendProgress<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">,<\/span> <span class=\"n\">progress<\/span> <span class=\"kt\">int<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c\">\/\/ Implementation depends on your WebSocket setup<\/span>\n    <span class=\"c\">\/\/ Example using gorilla\/websocket<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">ws<\/span><span class=\"p\">,<\/span> <span class=\"n\">ok<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">GetCtxVar<\/span><span class=\"p\">(<\/span><span class=\"s\">\"ws\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"p\">(<\/span><span class=\"o\">*<\/span><span class=\"n\">websocket<\/span><span class=\"o\">.<\/span><span class=\"n\">Conn<\/span><span class=\"p\">);<\/span> <span class=\"n\">ok<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">ws<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteJSON<\/span><span class=\"p\">(<\/span><span class=\"k\">map<\/span><span class=\"p\">[<\/span><span class=\"kt\">string<\/span><span class=\"p\">]<\/span><span class=\"k\">interface<\/span><span class=\"p\">{}{<\/span>\n            <span class=\"s\">\"progress\"<\/span><span class=\"o\">:<\/span> <span class=\"n\">progress<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">})<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"3_PDF_%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D9%88_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C\"><\/span>\n<p>  3. PDF \u062a\u0648\u0644\u06cc\u062f \u0648 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">PDFDownloadHandler<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c\">\/\/ Create PDF document<\/span>\n    <span class=\"n\">pdf<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">gofpdf<\/span><span class=\"o\">.<\/span><span class=\"n\">New<\/span><span class=\"p\">(<\/span><span class=\"s\">\"P\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"mm\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"A4\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">AddPage<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c\">\/\/ Add content<\/span>\n    <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">SetFont<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Arial\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"B\"<\/span><span class=\"p\">,<\/span> <span class=\"m\">16<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">Cell<\/span><span class=\"p\">(<\/span><span class=\"m\">40<\/span><span class=\"p\">,<\/span> <span class=\"m\">10<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Generated Report\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Add table<\/span>\n    <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">SetFont<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Arial\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"\"<\/span><span class=\"p\">,<\/span> <span class=\"m\">12<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">data<\/span> <span class=\"o\">:=<\/span> <span class=\"p\">[][]<\/span><span class=\"kt\">string<\/span><span class=\"p\">{<\/span>\n        <span class=\"p\">{<\/span><span class=\"s\">\"Column 1\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Column 2\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Column 3\"<\/span><span class=\"p\">},<\/span>\n        <span class=\"p\">{<\/span><span class=\"s\">\"Data 1\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Data 2\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Data 3\"<\/span><span class=\"p\">},<\/span>\n        <span class=\"c\">\/\/ ... more rows<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">for<\/span> <span class=\"n\">i<\/span><span class=\"p\">,<\/span> <span class=\"n\">row<\/span> <span class=\"o\">:=<\/span> <span class=\"k\">range<\/span> <span class=\"n\">data<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">for<\/span> <span class=\"n\">j<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span> <span class=\"o\">:=<\/span> <span class=\"k\">range<\/span> <span class=\"n\">row<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">Cell<\/span><span class=\"p\">(<\/span><span class=\"m\">40<\/span><span class=\"p\">,<\/span> <span class=\"m\">10<\/span><span class=\"p\">,<\/span> <span class=\"n\">col<\/span><span class=\"p\">)<\/span>\n            <span class=\"k\">if<\/span> <span class=\"n\">j<\/span> <span class=\"o\">==<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">row<\/span><span class=\"p\">)<\/span><span class=\"o\">-<\/span><span class=\"m\">1<\/span> <span class=\"p\">{<\/span>\n                <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">Ln<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n            <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n        <span class=\"k\">if<\/span> <span class=\"n\">i<\/span> <span class=\"o\">==<\/span> <span class=\"m\">0<\/span> <span class=\"p\">{<\/span>\n            <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">Ln<\/span><span class=\"p\">(<\/span><span class=\"o\">-<\/span><span class=\"m\">1<\/span><span class=\"p\">)<\/span>\n        <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ Set headers<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Type\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"application\/pdf\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Header<\/span><span class=\"p\">()<\/span><span class=\"o\">.<\/span><span class=\"n\">Set<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Content-Disposition\"<\/span><span class=\"p\">,<\/span> \n        <span class=\"s\">\"attachment; filename=report.pdf\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c\">\/\/ Write to response<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">pdf<\/span><span class=\"o\">.<\/span><span class=\"n\">Output<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">Writer<\/span><span class=\"p\">);<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">500<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"GOTCHA_%D9%87%D8%A7%DB%8C_%D9%85%D8%B4%D8%AA%D8%B1%DA%A9_%D8%A8%D8%B1%D8%A7%DB%8C_%D8%AC%D9%84%D9%88%DA%AF%DB%8C%D8%B1%DB%8C_%D8%A7%D8%B2\"><\/span>\n<p>  GOTCHA \u0647\u0627\u06cc \u0645\u0634\u062a\u0631\u06a9 \u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ol>\n<li>\n<p><strong>\u0646\u0634\u062a \u062d\u0627\u0641\u0638\u0647<\/strong> <\/p>\n<ul>\n<li>\u0647\u0645\u06cc\u0634\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f <code>defer<\/code> \u0628\u0631\u0627\u06cc \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc<\/li>\n<li>\u06a9\u0644 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627 \u0631\u0627 \u062f\u0631 \u062d\u0627\u0641\u0638\u0647 \u0646\u0645\u06cc \u062e\u0648\u0627\u0646\u06cc\u062f<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0645\u0633\u0627\u0626\u0644 \u0627\u0645\u0646\u06cc\u062a\u06cc<\/strong><\/p>\n<ul>\n<li>\u0645\u0633\u06cc\u0631\u0647\u0627\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0631\u0627 \u062a\u0623\u06cc\u06cc\u062f \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0645\u062c\u0648\u0632\u0647\u0627\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0627\u0646\u0648\u0627\u0639 \u067e\u0631\u0648\u0646\u062f\u0647 \u0631\u0627 \u0645\u062d\u062f\u0648\u062f \u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0645\u0634\u06a9\u0644\u0627\u062a \u0639\u0645\u0644\u06a9\u0631\u062f<\/strong><\/p>\n<ul>\n<li>\u0627\u0632 \u062e\u0648\u0627\u0646\u062f\u0646 \u0628\u0627\u0641\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u062d\u0627\u0641\u0638\u0647 \u067e\u0646\u0647\u0627\u0646 \u0645\u0646\u0627\u0633\u0628 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0628\u0633\u062a\u0646 \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627 \u0631\u0627 \u0641\u0631\u0627\u0645\u0648\u0634 \u0646\u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D8%AB%D8%A7%D9%84_%D8%AF%D8%B1_%D8%AF%D9%86%DB%8C%D8%A7%DB%8C_%D9%88%D8%A7%D9%82%D8%B9%DB%8C_%DB%8C%DA%A9_%D8%B3%D8%B1%D9%88%DB%8C%D8%B3_%D8%A8%D8%A7%D8%B1%DA%AF%DB%8C%D8%B1%DB%8C_%DA%A9%D8%A7%D9%85%D9%84\"><\/span>\n<p>  \u0645\u062b\u0627\u0644 \u062f\u0631 \u062f\u0646\u06cc\u0627\u06cc \u0648\u0627\u0642\u0639\u06cc: \u06cc\u06a9 \u0633\u0631\u0648\u06cc\u0633 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u06a9\u0627\u0645\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0633\u0631\u0648\u06cc\u0633 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 \u062a\u0631\u06a9\u06cc\u0628 \u062a\u0645\u0627\u0645 \u0645\u0641\u0627\u0647\u06cc\u0645\u06cc \u06a9\u0647 \u0645\u0648\u0631\u062f \u0628\u062d\u062b \u0642\u0631\u0627\u0631 \u062f\u0627\u062f\u0647 \u0627\u06cc\u0645 \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">type<\/span> <span class=\"n\">DownloadService<\/span> <span class=\"k\">struct<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">limiter<\/span>  <span class=\"o\">*<\/span><span class=\"n\">rate<\/span><span class=\"o\">.<\/span><span class=\"n\">Limiter<\/span>\n    <span class=\"n\">cache<\/span>    <span class=\"o\">*<\/span><span class=\"n\">Cache<\/span>\n    <span class=\"n\">metrics<\/span>  <span class=\"o\">*<\/span><span class=\"n\">Metrics<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">func<\/span> <span class=\"p\">(<\/span><span class=\"n\">s<\/span> <span class=\"o\">*<\/span><span class=\"n\">DownloadService<\/span><span class=\"p\">)<\/span> <span class=\"n\">ServeDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span> <span class=\"o\">*<\/span><span class=\"n\">ghttp<\/span><span class=\"o\">.<\/span><span class=\"n\">Request<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c\">\/\/ 1. Rate limiting<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">limiter<\/span><span class=\"o\">.<\/span><span class=\"n\">Wait<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Context<\/span><span class=\"p\">());<\/span> <span class=\"n\">err<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Response<\/span><span class=\"o\">.<\/span><span class=\"n\">WriteStatus<\/span><span class=\"p\">(<\/span><span class=\"m\">429<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ 2. Try cache<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">data<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">cache<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"file\"<\/span><span class=\"p\">)<\/span><span class=\"o\">.<\/span><span class=\"n\">String<\/span><span class=\"p\">());<\/span> <span class=\"n\">data<\/span> <span class=\"o\">!=<\/span> <span class=\"no\">nil<\/span> <span class=\"p\">{<\/span>\n        <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">metrics<\/span><span class=\"o\">.<\/span><span class=\"n\">RecordHit<\/span><span class=\"p\">()<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">serveContent<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">data<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c\">\/\/ 3. Stream file with resume support<\/span>\n    <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">streamWithResume<\/span><span class=\"p\">(<\/span><span class=\"n\">r<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A2%D8%B2%D9%85%D8%A7%DB%8C%D8%B4_%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C_%D8%AE%D9%88%D8%AF\"><\/span>\n<p>  \u0622\u0632\u0645\u0627\u06cc\u0634 \u0627\u062c\u0631\u0627\u06cc \u062e\u0648\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0641\u0631\u0627\u0645\u0648\u0634 \u0646\u06a9\u0646\u06cc\u062f \u06a9\u0647 \u0622\u0632\u0645\u0627\u06cc\u0634 \u06a9\u0646\u06cc\u062f! \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0645\u0648\u0631\u062f \u062a\u0633\u062a \u0633\u0631\u06cc\u0639 \u0628\u0631\u0627\u06cc \u0634\u0631\u0648\u0639 \u06a9\u0627\u0631 \u0648\u062c\u0648\u062f \u062f\u0627\u0631\u062f:<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight go\"><code><span class=\"k\">func<\/span> <span class=\"n\">TestDownload<\/span><span class=\"p\">(<\/span><span class=\"n\">t<\/span> <span class=\"o\">*<\/span><span class=\"n\">testing<\/span><span class=\"o\">.<\/span><span class=\"n\">T<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"n\">s<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Server<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">s<\/span><span class=\"o\">.<\/span><span class=\"n\">BindHandler<\/span><span class=\"p\">(<\/span><span class=\"s\">\"\/download\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">DownloadHandler<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">client<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">g<\/span><span class=\"o\">.<\/span><span class=\"n\">Client<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">r<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span> <span class=\"o\">:=<\/span> <span class=\"n\">client<\/span><span class=\"o\">.<\/span><span class=\"n\">Get<\/span><span class=\"p\">(<\/span><span class=\"s\">\"\/download?file=test.txt\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">assert<\/span><span class=\"o\">.<\/span><span class=\"n\">Nil<\/span><span class=\"p\">(<\/span><span class=\"n\">t<\/span><span class=\"p\">,<\/span> <span class=\"n\">err<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">assert<\/span><span class=\"o\">.<\/span><span class=\"n\">Equal<\/span><span class=\"p\">(<\/span><span class=\"n\">t<\/span><span class=\"p\">,<\/span> <span class=\"m\">200<\/span><span class=\"p\">,<\/span> <span class=\"n\">r<\/span><span class=\"o\">.<\/span><span class=\"n\">StatusCode<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n<div class=\"highlight__panel js-actions-panel\">\n<div class=\"highlight__panel-action js-fullscreen-code-action\">\n    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\"><title>\u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u0631\u0627 \u0648\u0627\u0631\u062f \u06a9\u0646\u06cc\u062f<\/title>\n    <path d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\"\/>\n<\/svg><\/p>\n<p>    <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\"><title>\u0627\u0632 \u062d\u0627\u0644\u062a \u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0647 \u062e\u0627\u0631\u062c \u0634\u0648\u06cc\u062f<\/title>\n    <path d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\"\/>\n<\/svg><\/p>\n<\/div>\n<\/div>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A8%D8%B3%D8%AA%D9%87_%D8%A8%D9%86%D8%AF%DB%8C\"><\/span>\n<p>  \u0628\u0633\u062a\u0647 \u0628\u0646\u062f\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0633\u0627\u062e\u062a \u0648 \u0633\u0627\u0632 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0647\u0627\u06cc \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 Goframe \u0641\u0642\u0637 \u0645\u0631\u0628\u0648\u0637 \u0628\u0647 \u062a\u0645\u0627\u0633 \u0646\u06cc\u0633\u062a <code>ServeFileDownload<\/code>\u0628\u0634\u0631 \u0627\u06cc\u0646 \u062f\u0631 \u0645\u0648\u0631\u062f:<\/p>\n<ul>\n<li>\u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0627\u0645\u0646\u06cc\u062a \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc<\/li>\n<li>\u0645\u062f\u06cc\u0631\u06cc\u062a \u0645\u0646\u0627\u0628\u0639 \u0628\u0647 \u0637\u0648\u0631 \u06a9\u0627\u0631\u0622\u0645\u062f<\/li>\n<li>\u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0627\u0632 \u0642\u0627\u0628\u0644\u06cc\u062a \u0647\u0627\u06cc \u0631\u0632\u0648\u0645\u0647<\/li>\n<li>\u0646\u0638\u0627\u0631\u062a \u0648 \u062d\u0641\u0638 \u0639\u0645\u0644\u06a9\u0631\u062f<\/li>\n<\/ul>\n<h3><span class=\"ez-toc-section\" id=\"%DA%86%D9%87_%DA%86%DB%8C%D8%B2%DB%8C_%D8%A8%D8%B9%D8%AF%DB%8C%D8%9F\"><\/span>\n<p>  \u0686\u0647 \u0686\u06cc\u0632\u06cc \u0628\u0639\u062f\u06cc\u061f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li>\u0631\u062f\u06cc\u0627\u0628\u06cc \u067e\u06cc\u0634\u0631\u0641\u062a \u0631\u0627 \u0628\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0627\u062f\u063a\u0627\u0645 \u0630\u062e\u06cc\u0631\u0647 \u0633\u0627\u0632\u06cc \u0627\u0628\u0631\u06cc \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc \u0627\u0632 \u067e\u06cc\u0634 \u067e\u0631\u062f\u0627\u0632\u0634 \u067e\u0631\u0648\u0646\u062f\u0647 \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u0641\u0634\u0631\u062f\u0647 \u0633\u0627\u0632\u06cc \u062c\u0631\u06cc\u0627\u0646 \u0631\u0627 \u06a9\u0627\u0648\u0634 \u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D9%86%D8%A7%D8%A8%D8%B9\"><\/span>\n<p>  \u0645\u0646\u0627\u0628\u0639<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06af\u0631 \u0633\u0624\u0627\u0644\u06cc \u062f\u0627\u0631\u06cc\u062f \u06cc\u0627 \u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u062f \u062a\u062c\u0631\u0628\u06cc\u0627\u062a \u062e\u0648\u062f \u0631\u0627 \u0628\u0627 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u062f\u0631 Go \u0628\u0647 \u0627\u0634\u062a\u0631\u0627\u06a9 \u0628\u06af\u0630\u0627\u0631\u06cc\u062f \u060c \u062f\u0631 \u0646\u0638\u0631\u0627\u062a \u0628\u0647 \u0645\u0646 \u0627\u0637\u0644\u0627\u0639 \u062f\u0647\u06cc\u062f! \ud83d\udcac<\/p>\n<hr\/>\n<p><em>\u0645\u062b\u0644 \u0627\u06cc\u0646 \u0645\u0642\u0627\u0644\u0647\u061f \u0628\u0631\u0627\u06cc \u0628\u06cc\u0634\u062a\u0631 \u0646\u06a9\u0627\u062a \u0648 \u0622\u0645\u0648\u0632\u0634 \u0647\u0627\u06cc \u062a\u0648\u0633\u0639\u0647 \u0628\u06cc\u0634\u062a\u0631 \u0645\u0631\u0627 \u062f\u0646\u0628\u0627\u0644 \u06a9\u0646\u06cc\u062f!<\/em> \ud83d\ude80<\/p>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0645\u0642\u062f\u0645\u0647 \u0633\u0644\u0627\u0645 devs! \u0627\u06af\u0631 \u062f\u0631 \u062d\u0627\u0644 \u0633\u0627\u062e\u062a \u0628\u0631\u0646\u0627\u0645\u0647 \u0647\u0627\u06cc \u0648\u0628 \u0628\u0627 GO \u0647\u0633\u062a\u06cc\u062f \u060c \u0627\u062d\u062a\u0645\u0627\u0644\u0627\u064b \u0628\u0627 \u0646\u06cc\u0627\u0632 \u0628\u0647 \u0631\u0633\u06cc\u062f\u06af\u06cc \u0628\u0647 \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u0641\u0627\u06cc\u0644 \u0631\u0648\u0628\u0631\u0648 \u0634\u062f\u0647 \u0627\u06cc\u062f. \u062f\u0631 \u062d\u0627\u0644\u06cc \u06a9\u0647 \u0645\u0645\u06a9\u0646 \u0627\u0633\u062a \u062f\u0631 \u0627\u0628\u062a\u062f\u0627 \u0633\u0627\u062f\u0647 \u0628\u0647 \u0646\u0638\u0631 \u0628\u0631\u0633\u062f \u060c \u0627\u062c\u0631\u0627\u06cc \u0628\u0627\u0631\u06af\u06cc\u0631\u06cc \u067e\u0631\u0648\u0646\u062f\u0647 \u0647\u0627\u06cc \u0622\u0645\u0627\u062f\u0647 \u062a\u0648\u0644\u06cc\u062f \u0628\u0627 \u0645\u062c\u0645\u0648\u0639\u0647 \u0686\u0627\u0644\u0634 \u0647\u0627\u06cc \u062e\u0627\u0635 \u062e\u0648\u062f \u0647\u0645\u0631\u0627\u0647 \u0627\u0633\u062a. \u062f\u0631 \u0627\u06cc\u0646 \u0631\u0627\u0647\u0646\u0645\u0627 \u060c &hellip;<\/p>\n","protected":false},"author":2,"featured_media":106309,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-106308","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/106308","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=106308"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/106308\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/106309"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=106308"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=106308"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=106308"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}