{"id":358633,"date":"2024-05-21T00:15:56","date_gmt":"2024-05-21T00:15:56","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=358633"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-05-21T00:15:56","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=358633","title":{"rendered":"<span>File upload \u043d\u0430 React.js \u0448\u0430\u0433 \u0437\u0430 \u0448\u0430\u0433\u043e\u043c<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/6c8\/4dd\/986\/6c84dd9868682c529305e69cc1d7f3fd.jpg\" width=\"1280\" height=\"698\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6c8\/4dd\/986\/6c84dd9868682c529305e69cc1d7f3fd.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>Drag and drop<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 \u0438 \u0441\u0430\u043c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u043d\u043e, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u043f\u0440\u0438\u0435\u043c\u044b \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u043d\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 &#8212; \u043b\u0435\u0433\u043a\u043e \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u0441\u044c. \u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0431\u0443\u0434\u044c \u044d\u0442\u043e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435, \u043f\u043e\u043b\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0438\u043b\u0438 \u0432\u0441\u0435 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e, \u043f\u043e\u0432\u0435\u0440\u0445 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435\u0433\u043e \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0447\u0442\u043e \u0434\u0430\u0441\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e\u043d\u044f\u0442\u044c &#8212; \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443. \u041f\u043e \u044d\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043e.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">const [url, setUrl] = useState();  return (   &lt;div>     &lt;Upload onUpload={setUrl}>       &lt;img src={url} alt=\"\" \/>     &lt;\/Upload>   &lt;\/div> )<\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ref \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 upload, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u043e\u043a\u043d\u043e \u0441 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<pre><code class=\"javascript\">const [url, setUrl] = useState();  const uploadRef = useRef(); return (   &lt;div>     &lt;Upload ref={uploadRef} onUpload={setUrl}>       &lt;img src={url} alt=\"\" \/>     &lt;\/Upload>     &lt;button onClick={() => uploadRef.current.upload()}>       \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b     &lt;\/button>   &lt;\/div> )<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u0432\u0435\u0441\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b, \u0431\u0443\u0434\u044c \u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430, \u0438\u043a\u043e\u043d\u043a\u0430, \u0438\u043b\u0438 \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0435\u0449\u0435.<\/p>\n<h2>Upload \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c input \u0441 \u0442\u0438\u043f\u043e\u043c file<\/p>\n<pre><code class=\"javascript\">const Upload = () => &lt;input type=\"file\" \/><\/code><\/pre>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/610\/e5e\/86f\/610e5e86f40378e5c20c6826433c715c.png\" width=\"478\" height=\"60\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/610\/e5e\/86f\/610e5e86f40378e5c20c6826433c715c.png\"\/><\/figure>\n<p>\u0421\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u043d\u043f\u0443\u0442 &#8212; \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u044b \u043f\u043e\u0439\u0434\u0435\u043c \u043f\u043e \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 &#8212; <strong>\u0441\u043a\u0440\u043e\u0435\u043c \u0438\u043d\u043f\u0443\u0442<\/strong> \u0441\u043e\u0432\u0441\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>display: none<\/strong>, \u0430 \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b. \u0427\u0442\u043e\u0431\u044b \u043a\u0430\u043a-\u0442\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0438\u043d\u0443\u0442\u043e\u043c, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0433\u043e \u0432 label \u0442\u0435\u0433, \u043b\u044e\u0431\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 label \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 input.<\/p>\n<pre><code class=\"javascript\">const Upload = () => (   &lt;label>     &lt;input type=\"file\" \/>   &lt;\/label> )<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0445\u0443\u043a\u043e\u043c useId, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 id \u0438 \u0441\u0432\u044f\u0437\u0430\u0442\u044c label \u0438 input. \u0421\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u0430\u0433, \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c input \u0432 label \u0443\u0436\u0435 \u0441\u0432\u044f\u0436\u0435\u0442 \u044d\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043e\u0434\u043d\u0430\u043a\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e id.<\/p>\n<pre><code class=\"javascript\">const Upload = () => {   const id = useId()   return (     &lt;label htmlFor={id}>       &lt;input type=\"file\" id={id} \/>     &lt;\/label>   ) }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u0430\u043a \u0443\u0433\u043e\u0434\u043d\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c label, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c <strong>\u043d\u0443\u0436\u043d\u043e<\/strong> \u0431\u0443\u0434\u0435\u0442 <strong>\u0437\u0430\u0434\u0430\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443 <\/strong>\u0438<strong> \u0432\u044b\u0441\u043e\u0442\u0443<\/strong>, \u043d\u0443 \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 label \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043a\u043e\u0448\u043a\u043e \u0441 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432. \u0421\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u0432 \u043a\u043e\u043d\u0446\u0435, \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u0432\u043b\u0435\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<h2>Upload \u0444\u0443\u043d\u043a\u0446\u0438\u044f. \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<h3>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0442\u0438\u043f\u044b<\/h3>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u0442\u043e\u0439 \u0438 \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u0430 \u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0447\u0443\u0439\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c\u043e\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u041c\u043e\u0436\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <a href=\"https:\/\/github.com\/axios\/axios\">axios<\/a> \u0438 \u0435\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043e\u043d \u0443\u0436\u0435 \u0435\u0441\u0442\u044c &#8212; \u0442\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u043e, \u0435\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442, \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0440\u0430\u0434\u0438 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f &#8212; \u0442\u0430\u043a\u0430\u044f \u0441\u0435\u0431\u0435 \u0438\u0434\u0435\u044f. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e XMLHttpRequest, \u043a\u0441\u0442\u0430\u0442\u0438 \u0442\u043e\u0442 \u0436\u0435 axios \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f upload \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c file, url, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0446\u0438\u0439. \u041f\u0443\u0441\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f onProgress, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u043d\u0442, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(   file: File,   url: string,   options?: { onProgress?: (progress: number) => void } ): Promise&lt;T> => {}<\/code><\/pre>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430? \u042d\u0442\u043e \u043e\u043f\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0441\u0442\u0438\/\u0437\u0430\u043a\u0440\u044b\u0442\u043e\u0441\u0442\u0438 \u0438 \u043a\u043d\u0438\u0433\u0443 &#171;<a href=\"https:\/\/www.litres.ru\/book\/robert-s-martin\/chistyy-kod-sozdanie-analiz-i-refaktoring-pdf-epub-6444478\/\">\u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434<\/a>&#171;.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 3-\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u044d\u0442\u043e \u043f\u043e\u0447\u0435\u0440\u043f\u043d\u0443\u0442\u043e \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 &#171;\u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434&#187;. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c &#171;\u043a\u0432\u043e\u0442\u0443&#187;, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 &#171;\u0437\u0430\u043a\u0440\u044b\u0442\u0430&#187; \u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u043d\u043e &#171;\u043e\u0442\u043a\u0440\u044b\u0442\u0430&#187; \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u043c, \u043c\u044b \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0446\u0438\u044e \u0438 \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0441\u043b\u043e\u043c\u0430\u0435\u0442 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434. <\/p>\n<p>\u0415\u0449\u0435 \u0445\u043e\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u043e\u0442 \u044d\u0442\u0443 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e <code>upload = &lt;T>(): Promise&lt;T><\/code><\/p>\n<p>\u042d\u0442\u043e \u0434\u0436\u0435\u043d\u0435\u0440\u0438\u043a, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0435\u0440\u043d\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f, \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u0440\u043e\u043c\u0438\u0441 (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/188\/1ac\/c12\/1881acc12d9c93d9b29ee26ac70b5adf.png\" width=\"808\" height=\"112\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/188\/1ac\/c12\/1881acc12d9c93d9b29ee26ac70b5adf.png\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b40\/04a\/9d9\/b4004a9d983f828f3f9b2dacff7bdfdf.png\" width=\"846\" height=\"116\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b40\/04a\/9d9\/b4004a9d983f828f3f9b2dacff7bdfdf.png\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/239\/619\/01c\/23961901c875157ff59d6e659ddb6fa6.png\" width=\"1050\" height=\"120\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/239\/619\/01c\/23961901c875157ff59d6e659ddb6fa6.png\"\/><\/figure>\n<p>\u0421 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438\u0441\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043a\u0443\u0445\u043d\u0435\u0439.<\/p>\n<h3>\u0417\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e XMLHttpRequest<\/h3>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c XMLHttpRequest, \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043d\u0438\u043c \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 4 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u0430:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 XMLHttpRequest<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"javascript\">\/\/ \u0428\u0430\u0433 1 \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 XMLHttprequest const xhr = new XMLHttpRequest();  \/\/ \u0428\u0430\u0433 2 \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 xhr.open('POST', url);  \/\/ \u0428\u0430\u0433 3 \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 xhr.onload = () => {   if (xhr.status === 200) {     \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430   } else {     \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a   } };  \/\/ \u0428\u0430\u0433 4 \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 xhr.send(myData);<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0441 fetch, \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0431\u043e\u043b\u0435\u0435 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u0439, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0437\u043d\u0430\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u044b\u043b\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e, \u0447\u0435\u043c \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0445\u0432\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f fetch \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e abort \u0434\u043b\u044f \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0417\u0430\u0432\u0435\u0440\u043d\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e. \u041e\u0431\u0440\u0430\u0449\u0430\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0444\u0443\u043d\u043a\u0446\u0438\u044f upload \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u043c\u0438\u0441 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 then, catch, finally, \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0442\u043e\u043d \u0434\u043b\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043d\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 api.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);          xhr.onload = () => {       if (xhr.status === 200) {         \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430         resolve(\/* \u0441\u044e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 *\/)       } else {         \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a         reject(\/* \u0441\u044e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443 *\/)       }     };          xhr.send(myData);   }) }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u043f\u0440\u043e\u043c\u0438\u0441\u0430\u043c\u0438, \u0442\u043e \u0432 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const fn = () => new Promise((resolve, reject) => {   \/\/ \u041d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440   resolve(data); \/\/ \u0422\u043e \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 resolve \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 .then()   reject(error); \/\/ \u0422\u043e \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 reject \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 .catch() });  fn().then(data => {}).catch(error => {});<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b.<\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u0430<\/h3>\n<p>\u041d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b, \u0447\u0430\u0441\u0442\u043e \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0442\u0435\u043a\u0441\u0442 \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Content-Type \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/API\/FormData\">FormData<\/a> \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 append \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u0444\u0430\u0439\u043b \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e, \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Content-Type \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<pre><code class=\"javascript\">\/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 const myData = new FormData(); \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u043a\u043b\u044e\u0447\u043e\u043c 'my_file', \u0442\u0443\u0442 \u0432\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441, \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u0436\u0435 myData.append('my_file' \/* &lt;- \u044d\u0442\u043e \u043a\u043b\u044e\u0447 *\/, file);  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 xhr.send(myData);<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u0434\u043e \u0442\u043e\u0447\u043d\u043e \u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u044e\u0447 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u044f \u0443\u043a\u0430\u0437\u0430\u043b \u043a\u043b\u044e\u0447 <code>\"my_file\"<\/code>, \u043e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0442\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 express.js (\u0431\u0435\u043a\u0435\u043d\u0434)<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u0430 express.js \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const app = express();  app.post('\/upload', (request, response) => {   const file = request.files.my_file; \/\/ &lt;- \u00a0\u0432\u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430   \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0444\u0430\u0439\u043b\u0430   \/\/ ...   \/\/ \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435   \/\/ ...   \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435    \/\/ ...   \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c url \u0444\u0430\u0439\u043b\u0430   response.send({ url: file_url }) });<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421 \u0443\u0447\u0435\u0442\u043e\u043c \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0444\u0430\u0439\u043b\u0430, \u0444\u0443\u043d\u043a\u0446\u0438\u044f upload \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);          xhr.onload = () => {       if (xhr.status === 200) {         resolve(\/*  *\/)       } else {         reject(\/*  *\/)       }     };      \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0443 \u0444\u0430\u0439\u043b\u0430     const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) }<\/code><\/pre>\n<h3>\u041f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440<\/h3>\n<p>\u0423 XMLHttpRequest \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e upload, \u0438 \u043d\u0430 \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0441\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a onprogress, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0439\u0442. \u042d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 onProgress \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430.<\/p>\n<pre><code class=\"javascript\">xhr.upload.onprogress = (event) => {   \/\/ event.total - \u043e\u0431\u0449\u0438\u0439 \u0432\u0435\u0441 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445   \/\/ event.loaded - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0431\u0430\u0439\u0442   \/\/ Math.round((event.loaded \/ event.total) * 100) - \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043e\u0442 1 \u0434\u043e 100   onProgress(Math.round((event.loaded \/ event.total) * 100)); };<\/code><\/pre>\n<p>\u0421 \u044d\u0442\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   \/\/ \u0414\u043e\u0441\u0442\u0430\u043b\u0438 onProgress \u0438\u0437 options   const onProgress = options?.onProgress;   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);      \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430     xhr.upload.onprogress = (event) => {       onProgress?.(Math.round((event.loaded \/ event.total) * 100));     };          xhr.onload = () => {       if (xhr.status === 200) {         resolve(\/*  *\/)       } else {         reject(\/*  *\/)       }     };      const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) }<\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 XMLHttpRequest \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0436\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f json \u043a\u0430\u043a \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u043e \u044d\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u043e\u0432 json: <code>xhr.responseType = 'json'<\/code><\/p>\n<p>\u0422\u0430\u043a \u0432 <code>xhr.response<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0443\u0436\u0435 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u0439 json, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c <code>xhr.response<\/code> \u0432 <code>resolve<\/code> \u0438 <code>reject<\/code>.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   const onProgress = options?.onProgress;   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();          \/\/ \u0423\u043a\u0430\u0437\u0430\u043b\u0438 \u0442\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u0430. xhr.response \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u043c json-\u043e\u043c     xhr.responseType = 'json';          xhr.open('POST', url);      xhr.upload.onprogress = (event) => {       onProgress?.(Math.round((event.loaded \/ event.total) * 100));     };      \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430. \u0412 xhr.response \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442 \u043a\u0430\u043a \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0442\u0430\u043a \u0438 \u043e\u0448\u0438\u0431\u043a\u043e\u0439     \/\/ \u041e\u0442\u043b\u0438\u0447\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0432 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 (\u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d)     xhr.onload = () => {       if (xhr.status === 200) resolve(xhr.response);       else reject(xhr.response);     };      const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) }<\/code><\/pre>\n<h3>\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/h3>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 <code>xhr.abort<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0443 \u043d\u0435\u0433\u043e \u0441\u043b\u0430\u0431\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u043e\u043d \u0445\u043e\u0447\u0435\u0442 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0448\u0443\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0444\u0430\u0439\u043b\u0430. \u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430\u0440\u0443\u0436\u0443.<\/p>\n<p>\u041d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043d\u0430\u0440\u0443\u0448\u0430\u0442\u044c \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e\u0441\u0442\u044c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u043e\u043c\u0438\u0441\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u0440\u043e\u043c\u0438\u0441\u043e\u043c \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">\/\/ \u0420\u0430\u0431\u043e\u0447\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043d\u043e \u043d\u0435 \u0441\u0442\u0440\u043e\u0439\u043d\u043e\u0435 \u0438 \u043d\u0435 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u043e\u0435 const upload = &lt;T>() => { promise: Promise&lt;T>; abort: () => void }  \/\/ \u041b\u0443\u0447\u0448\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 const upload = &lt;T>() => Promise&lt;T><\/code><\/pre>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e\u043c js, \u0432\u0441\u0435 \u0432 js &#8212; \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u0432 \u043d\u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430. \u0422\u0430\u043a \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c, \u0434\u043e\u0431\u0430\u0432\u0438\u0442 \u0432 \u043f\u0440\u043e\u043c\u0438\u0441 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e abort. \u0422\u0438\u043f\u044b \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">export type UploadPromise&lt;T> = Promise&lt;T> &amp; { abort: () => void };  const upload = &lt;T>() => UploadPromise&lt;T><\/code><\/pre>\n<p>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">export type UploadPromise&lt;T> = Promise&lt;T> &amp; { abort: () => void };  export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): UploadPromise&lt;T> => {   \/\/ \u0412\u044b\u0442\u0430\u0449\u0438\u043b\u0438 xhr \u0438\u0437 Promise, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u043a\u0438\u043d\u0443\u0442\u044c abort   const xhr = new XMLHttpRequest();   xhr.responseType = 'json';    const onProgress = options?.onProgress;      const promise = new Promise((resolve, reject) => {     xhr.open('POST', url);      xhr.upload.onprogress = (event) => {       onProgress?.(Math.round((event.loaded \/ event.total) * 100));     };      xhr.onload = () => {       if (xhr.status === 200) resolve(xhr.response);       else reject(xhr.response);     };      const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) as UploadPromise&lt;T>;      \/\/ \u041f\u0440\u0438\u0441\u0432\u043e\u0438\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e abort, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0440\u0432\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441   promise.abort = () => xhr.abort();    return promise; }<\/code><\/pre>\n<p>\u0412\u0430\u0436\u043d\u043e\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435, \u0432 \u043b\u0443\u0447\u0448\u0438\u0445 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u044f\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0441\u043e\u0431\u043b\u0430\u0437\u043d \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435 \u0442\u0430\u043a <code>promise.abort = () => xhr.abort();<\/code>, \u0430 \u0432\u043e\u0442 \u0442\u0430\u043a <code>promise.abort = xhr.abort;<\/code>, \u043d\u043e, \u0432 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043e\u0448\u0438\u0431\u043a\u0443 <code>Illegal invocation<\/code>. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435 \u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>promise.abort = () => xhr.abort();<\/code>.<\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e! \u0424\u0443\u043d\u043a\u0446\u0438\u044f upload \u0433\u043e\u0442\u043e\u0432\u0430! \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0435\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0447\u0435\u043c \u0438 \u0437\u0430\u0439\u043c\u0435\u043c\u0441\u044f \u043d\u0438\u0436\u0435.<\/p>\n<h2>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e input file<\/h2>\n<p>\u0412\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u0435\u0449\u0435 \u0440\u0430\u0437 \u043d\u0430 \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/p>\n<pre><code class=\"javascript\">const Upload = () => {   const id = useId()   return (     &lt;label htmlFor={id}>       &lt;input type=\"file\" id={id} \/>     &lt;\/label>   ) }<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>handleFileChange<\/code> \u0434\u043b\u044f input<\/p>\n<pre><code class=\"javascript\">const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {   \/\/ event.target - \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442   \/\/ target.files - \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u043d\u043f\u0443\u0442\u0430, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0435\u0440\u0435\u043c \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b   handleFile(event.target.files[0]); };<\/code><\/pre>\n<p>\u0412 \u043d\u0435\u0439 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>handleFile<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c \u0438 \u0432 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e drag and drop.<\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>handleFile<\/code>. \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">const handleFile = (file: File) => {   \/\/ \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u0435\u0442 - \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c    if (!file) return;    const uploading = upload&lt;T>(file, url);   uploading     .then(onUpload) \/\/ \u0422\u043e \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 - \u043e\u0442\u0434\u0430\u0435\u043c \u043d\u0430\u0440\u0443\u0436\u0443     .catch((e) => {\/* \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a *\/}) };<\/code><\/pre>\n<p>\u0410 \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void; }  const Upload: FC&lt;UploadProps> = ({ onUpload }) => {   const handleFile = (file: File) => {     if (!file) return;        const uploading = upload&lt;T>(file, url);     uploading       .then(onUpload)       .catch((e) => {})   };    const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {     handleFile(event.target.files[0]);   };      const id = useId()   return (     &lt;label htmlFor={id}>       &lt;input type=\"file\" id={id} onChange={handleFileChange} \/>     &lt;\/label>   ) }<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u043d\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0434\u0432\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 handleFile<\/p>\n<h2>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/h2>\n<pre><code class=\"javascript\">const [progress, setProgress] = useState(0); const [loading, setLoading] = useState(false);  \/\/ \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0441\u0431\u0440\u043e\u0441\u0430, \u043e\u043d\u0430 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0432 \u0434\u0432\u0443\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 const reset = () => {   setLoading(false);   setProgress(0); }  const handleFile = (file: File) => {   \/\/ \u0415\u0441\u043b\u0438 \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u0435\u0442 - \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0442\u044c    if (loading || !file) return;    setLoading(true);   \/\/ onProgress \u0431\u0443\u0434\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 progress   const uploading = upload&lt;T>(file, url, { onProgress: setProgress });   uploading     .then(onUpload)     .catch((e) => {})     .finally(reset) \/\/ \u0425\u043e\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0430, \u0445\u043e\u0442\u044c \u0443\u0441\u043f\u0435\u0445 - \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0438 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 };<\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u044d\u0442\u0430\u043f\u0435 \u044f \u043e\u0431\u0435\u0440\u043d\u0443 label \u0432 div \u0438 \u043f\u043e\u043b\u043e\u0436\u0443 \u0440\u044f\u0434\u043e\u043c \u0441 label \u0435\u0449\u0435 \u043e\u0434\u0438\u043d div. \u042d\u0442\u043e\u0442 div \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0442\u044c label, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043d\u0438\u043c \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u0430. JSX \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c. \u0422\u0430\u043a\u0436\u0435 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0432 \u043d\u0430\u0448\u0438 props.<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void;   className?: string;   children: React.ReactNode;   overlay?: boolean;   disabled?: boolean; }  return (   &lt;div className={cn(s.root, className)}>     {children}     &lt;label htmlFor={id} className={cn(s.label, overlay &amp;&amp; s.visible)}>       &lt;input         disabled={disabled}         type=\"file\"         className={s.input}         onChange={handleFileChange}         id={id}       \/>       &lt;UploadOutlined className={s.icon} \/>     &lt;\/label>     {loading &amp;&amp; (       &lt;div className={s.loading}>         &lt;LoadingOutlined className={s.icon} \/>         &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>         &lt;CloseCircleOutlined className={s.abort} onClick={abort} \/>       &lt;\/div>     )}   &lt;\/div> );<\/code><\/pre>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/habr.com\/ru\/articles\/335244\/\">css \u043c\u043e\u0434\u0443\u043b\u0438<\/a>, \u043f\u043e\u0442\u043e\u043c\u0443 \u043f\u0443\u0441\u0442\u044c \u0432\u0430\u0441 \u043d\u0435 \u043f\u0443\u0433\u0430\u044e\u0442 css \u043a\u043b\u0430\u0441\u0441\u044b <code>s.root<\/code>, <code>s.label<\/code>, <code>s.input<\/code> &#8212; \u0432\u0441\u0435 \u043e\u043d\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0438. \u0410 \u043c\u043d\u0435 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c css \u043d\u0435 \u0432\u043e\u043b\u043d\u0443\u044f\u0441\u044c \u043e \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u0438 \u0438\u043c\u0435\u043d css \u043a\u043b\u0430\u0441\u0441\u043e\u0432. \u0412\u043e\u0442 \u044d\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u044c <code>cn(s.root, className)<\/code> &#8212; \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043c\u043e\u0435\u0433\u043e \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e css \u043a\u043b\u0430\u0441\u0441\u0430 \u0441 \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0441\u043d\u0430\u0440\u0443\u0436\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u0410 \u0432\u043e\u0442 \u044d\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u044c <code>cn(s.label, overlay &amp;&amp; s.visible)<\/code> , \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 &#8212;  \u0435\u0441\u043b\u0438 overlay true, \u0442\u043e \u043a label \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 <code>visible<\/code>, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443, \u043f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0442\u0438\u0435 \u0441 upload \u0438\u043a\u043e\u043d\u043a\u043e\u0439.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/807\/e4a\/a18\/807e4aa1845ae6ce265e9edb3ae22a80.gif\" alt=\"&lt;Upload overlay \/> \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u0448\u0430\u0442\u044c \u043f\u0440\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0438\u043d\u043f\u0443\u0442\u043e\u0432&#187; title=&#187;&lt;Upload overlay \/> \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u0448\u0430\u0442\u044c \u043f\u0440\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0438\u043d\u043f\u0443\u0442\u043e\u0432&#187; width=&#187;1212&#8243; height=&#187;578&#8243; data-src=&#187;https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/807\/e4a\/a18\/807e4aa1845ae6ce265e9edb3ae22a80.gif&#187;\/><\/p>\n<div><figcaption><code>&lt;Upload overlay \/><\/code> \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043a\u0430\u0440\u0442\u0438\u043d\u043e\u043a, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u0448\u0430\u0442\u044c \u043f\u0440\u0438 \u043e\u0431\u0435\u0440\u0442\u043a\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0438\u043d\u043f\u0443\u0442\u043e\u0432<\/figcaption><\/div>\n<\/figure>\n<p> \u0412 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u044f \u0441\u0434\u0435\u043b\u0430\u043b position relative \u0434\u043b\u044f \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e div, \u0447\u0442\u043e\u0431\u044b label \u0438 div.loading \u0441\u0434\u0435\u043b\u0430\u0442\u044c position absolute. \u0420\u0430\u0441\u0442\u044f\u0433\u0438\u0432\u0430\u044e \u0438\u0445 \u043f\u043e \u0432\u0441\u0435\u043c\u0443 div, \u0442\u0430\u043a div.loading \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0432\u0430\u0442\u044c label, \u0430 label \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u044b\u0442\u044c, \u0435\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Upload \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043a\u0430\u043a \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0445 \u0438\u043d\u043f\u0443\u0442\u043e\u0432. <\/p>\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c \u043d\u0435 \u0445\u043e\u0447\u0443 \u0432\u0430\u0441 \u0443\u0442\u043e\u043c\u043b\u044f\u0442\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u0432\u0441\u0435\u0445 \u0441\u0442\u0438\u043b\u0435\u0439. \u041f\u0440\u0438\u0432\u043e\u0436\u0443 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 sass \u0444\u0430\u0439\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u0441\u0442\u0438\u043b\u0438 \u0438 \u0434\u043b\u044f drag and drop \u0438 \u0434\u043b\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u043e\u0442\u043c\u0435\u043d\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0415\u0441\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c &#8212; \u0431\u0443\u0434\u0443 \u0440\u0430\u0434 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u0442\u0438\u043b\u0438 \u043d\u0430 sass <\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">.root   position: relative   font-size: 0   z-index: 0    &amp;:hover     .label       opacity: 0.5    .progress     margin-top: 32px     margin-bottom: 12px     width: 62%  .icon   font-size: 48px   color: var(--whiteColor)  .abort   font-size: 21px   color: var(--whiteColor)  .label   pointer-events: none   position: absolute   display: flex   align-items: center   justify-content: center   opacity: 0   background-color: var(--gray1Color)   transition: 0.3s   top: 0   left: 0   right: 0   bottom: 0   width: 100%   height: 100%   z-index: 1   visibility: hidden    &amp;.visible     pointer-events: auto     visibility: visible    &amp;.drop     visibility: visible     opacity: 0.5  .input   display: none  .loading   position: absolute   display: flex   align-items: center   justify-content: center   flex-direction: column   top: 0   left: 0   right: 0   bottom: 0   width: 100%   height: 100%   z-index: 2   background-color: rgba(var(--gray1Color), 0.5) <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441. \u041e\u0431\u0440\u0430\u0449\u0430\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0443 \u043c\u0435\u043d\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0432 \u0432\u0438\u0434\u0435 \u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u0438\u043a\u043e\u043d\u043a\u0438 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430. \u0423 \u0432\u0430\u0441 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a \u0443\u0433\u043e\u0434\u043d\u043e.<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void;   className?: string;   children: React.ReactNode;   overlay?: boolean;   disabled?: boolean; }  const Upload: FC&lt;UploadProps> = ({    onUpload,   disabled,   overlay = true,   children,   className }) => {   const [progress, setProgress] = useState(0);   const [loading, setLoading] = useState(false);      const reset = () => {     setLoading(false);     setProgress(0);   }      const handleFile = (file: File) => {     if (loading || !file) return;        setLoading(true);     const uploading = upload&lt;T>(file, url, { onProgress: setProgress });     uploading       .then(onUpload)       .catch((e) => {})       .finally(reset)   };    const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {     handleFile(event.target.files[0]);   };      const id = useId()   return (     &lt;div className={cn(s.root, className)}>       {children}       &lt;label htmlFor={id} className={cn(s.label, overlay &amp;&amp; s.visible)}>         &lt;input           disabled={disabled}           type=\"file\"           className={s.input}           onChange={handleFileChange}           id={id}         \/>         &lt;UploadOutlined className={s.icon} \/>       &lt;\/label>       {loading &amp;&amp; (         &lt;div className={s.loading}>           &lt;LoadingOutlined className={s.icon} \/>           &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>         &lt;\/div>       )}     &lt;\/div>   ); }<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8d0\/aba\/354\/8d0aba3545d96719fa2f86aa6a6e6653.gif\" width=\"1212\" height=\"530\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8d0\/aba\/354\/8d0aba3545d96719fa2f86aa6a6e6653.gif\"\/><\/figure>\n<h2>\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e abort, \u0432\u043d\u0443\u0442\u0440\u0438 \u0435\u0435 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c reset (\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0432\u0442\u043e\u0440\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f), \u0438 abortUploading ref, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044e abort \u0438\u0437 upload \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<pre><code class=\"javascript\">const abortUploading = useRef&lt;() => void>();  const abort = () => {   \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 ?. \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u0435 \u0431\u044b\u043b\u043e, \u0430 \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0435\u0435 \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c   abortUploading.current?.();   reset(); };  const handleFile = (file: File) => {   if (loading || !file) return;    setLoading(true);   const uploading = upload&lt;T>(file, url, { onProgress: setProgress });   \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e abort   abortUploading.current = uploading.abort;   uploading     .then(onUpload)     .catch((e) => {})     .finally(reset) };  \/\/ ---    return (     ...       {loading &amp;&amp; (         &lt;div className={s.loading}>           &lt;LoadingOutlined className={s.icon} \/>           &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>           \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0443, \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u044e\u0449\u0443\u044e \u0437\u0430\u043f\u0440\u043e\u0441           &lt;CloseCircleOutlined className={s.abort} onClick={abort} \/>         &lt;\/div>       )}     ...   );<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void;   className?: string;   children: React.ReactNode;   overlay?: boolean;   disabled?: boolean; }  const Upload: FC&lt;UploadProps> = ({    onUpload,   disabled,   overlay = true,   children,   className }) => {   const [progress, setProgress] = useState(0);   const [loading, setLoading] = useState(false);    const abortUploading = useRef&lt;() => void>();      const abort = () => {     abortUploading.current?.();     reset();   };      const reset = () => {     setLoading(false);     setProgress(0);   }      const handleFile = (file: File) => {     if (loading || !file) return;        setLoading(true);     const uploading = upload&lt;T>(file, url, { onProgress: setProgress });     abortUploading.current = uploading.abort;     uploading       .then(onUpload)       .catch((e) => {})       .finally(reset)   };    const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {     handleFile(event.target.files[0]);   };      const id = useId()   return (     &lt;div className={cn(s.root, className)}>       {children}       &lt;label htmlFor={id} className={cn(s.label, overlay &amp;&amp; s.visible)}>         &lt;input           disabled={disabled}           type=\"file\"           className={s.input}           onChange={handleFileChange}           id={id}         \/>         &lt;UploadOutlined className={s.icon} \/>       &lt;\/label>       {loading &amp;&amp; (         &lt;div className={s.loading}>           &lt;LoadingOutlined className={s.icon} \/>           &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>           &lt;CloseCircleOutlined className={s.abort} onClick={abort} \/>         &lt;\/div>       )}     &lt;\/div>   ); }<\/code><\/pre>\n<h2>Drag and drop<\/h2>\n<p>Drag and drop \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430\u0432\u0435\u0448\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043d\u0430 onDrag \u0438 onDrop. \u042d\u0442\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0448\u0438\u0432\u0430\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u0423\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 &#8212; \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u0430, \u0438 label \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043a\u0440\u044b\u0442, \u043f\u043e\u0432\u0435\u0441\u0438\u043c \u044d\u0442\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0430 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 div.<\/p>\n<pre><code class=\"javascript\">const [drop, setDrop] = useState(false);  const onDragLeave = (e: React.DragEvent&lt;HTMLElement>) => {   if (disabled) return;   e.preventDefault();   setDrop(false); };  const onDragOver = (e: React.DragEvent&lt;HTMLElement>) => {   if (disabled) return;   e.preventDefault();   setDrop(true); };  const handleDrop = (e: React.DragEvent&lt;HTMLElement>) => {   if (disabled) return;   e.preventDefault();   const droppedFile = e.dataTransfer.files[0];   setDrop(false);    handleFile(droppedFile); };  return (   &lt;div     className={cn(s.root, className)}     onDrop={handleDrop}     onDragOver={onDragOver}     onDragLeave={onDragLeave}   >     ...   &lt;\/div> );<\/code><\/pre>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0440\u0438? \u0412\u043e\u043e\u0431\u0449\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e 2-\u0445, \u044d\u0442\u043e onDragOver \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c e.preventDefault(); \u0438\u043d\u0430\u0447\u0435 \u0444\u0430\u0439\u043b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043e\u0442\u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0432 \u043d\u043e\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u0422\u0430\u043a\u0436\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u0435\u043d onDrop, \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b &#171;\u0443\u0440\u043e\u043d\u0438\u043b\u0438&#187; \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u044d\u0442\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u041c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u043b, \u0447\u0442\u043e \u0432 \u043d\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e &#171;\u0443\u0440\u043e\u043d\u0438\u0442\u044c&#187; \u0444\u0430\u0439\u043b, \u0438 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043c\u044b\u0448\u044c \u0441 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u043e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b \u0441\u0432\u043e\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 &#8212; \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0432\u0435\u0441\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a onDragLeave, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b\u0448\u044c \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u043f\u043e\u043a\u0438\u043d\u0443\u043b\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. onDragLeave &#8212; \u044d\u0442\u043e \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u0441\u0431\u0440\u043e\u0441\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f drop.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b &#171;\u0443\u0440\u043e\u043d\u0438\u043c&#187; \u0444\u0430\u0439\u043b\u044b \u0432 div, \u043e\u043d\u0438 \u043f\u043e\u043f\u0430\u0434\u0443\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e handleDrop, \u0433\u0434\u0435 \u043c\u044b \u0441\u0431\u0440\u043e\u0441\u0438\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f drop \u0438 \u0431\u0443\u0434\u0435\u043c \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 handleFile.<\/p>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void;   className?: string;   children: React.ReactNode;   overlay?: boolean;   disabled?: boolean; }  const Upload: FC&lt;UploadProps> = ({    onUpload,   disabled,   overlay = true,   children,   className }) => {   const [progress, setProgress] = useState(0);   const [drop, setDrop] = useState(false);   const [loading, setLoading] = useState(false);    const abortUploading = useRef&lt;() => void>();      const abort = () => {     abortUploading.current?.();     reset();   };      const reset = () => {     setLoading(false);     setProgress(0);   }      const handleFile = (file: File) => {     if (loading || !file) return;        setLoading(true);     const uploading = upload&lt;T>(file, url, { onProgress: setProgress });     abortUploading.current = uploading.abort;     uploading       .then(onUpload)       .catch((e) => {})       .finally(reset)   };    const onDragLeave = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     setDrop(false);   };      const onDragOver = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     setDrop(true);   };      const handleDrop = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     const droppedFile = e.dataTransfer.files[0];     setDrop(false);        handleFile(droppedFile);   };    const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {     handleFile(event.target.files[0]);   };      const id = useId()   return (     &lt;div        className={cn(s.root, className)}       onDrop={handleDrop}       onDragOver={onDragOver}       onDragLeave={onDragLeave}     >       {children}       \/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 s.drop \u0435\u0441\u043b\u0438 drop       &lt;label htmlFor={id} className={cn(s.label, overlay &amp;&amp; s.visible, drop &amp;&amp; s.drop)}>         &lt;input           disabled={disabled}           type=\"file\"           className={s.input}           onChange={handleFileChange}           id={id}         \/>         &lt;UploadOutlined className={s.icon} \/>       &lt;\/label>       {loading &amp;&amp; (         &lt;div className={s.loading}>           &lt;LoadingOutlined className={s.icon} \/>           &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>           &lt;CloseCircleOutlined className={s.abort} onClick={abort} \/>         &lt;\/div>       )}     &lt;\/div>   ); }<\/code><\/pre>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0442\u043e\u0432, \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0438 \u0448\u0442\u0440\u0438\u0445\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ref \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 upload \u0438 \u043c\u0435\u0442\u043e\u0434 abort.<\/p>\n<h2>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f ref \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/h2>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432 forwardRef, \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u0438\u043f UploadRef \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c useImperativeHandle \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432.<\/p>\n<pre><code class=\"javascript\">export type UploadProps = {   onUpload: (data: unknown) => void;   className?: string;   children: React.ReactNode;   overlay?: boolean;   disabled?: boolean; }  export type UploadRef = {   upload: () => void;   abort: () => void; }  export const Upload = forwardRef&lt;UploadRef, UploadProps>(({    onUpload,   disabled,   overlay = true,   children,   className }, ref) => {   const [progress, setProgress] = useState(0);   const [drop, setDrop] = useState(false);   const [loading, setLoading] = useState(false);    const abortUploading = useRef&lt;() => void>();      const abort = () => {     abortUploading.current?.();     reset();   };      const reset = () => {     setLoading(false);     setProgress(0);   }      const handleFile = (file: File) => {     if (loading || !file) return;        setLoading(true);     const uploading = upload&lt;T>(file, url, { onProgress: setProgress });     abortUploading.current = uploading.abort;     uploading       .then(onUpload)       .catch((e) => {})       .finally(reset)   };    const onDragLeave = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     setDrop(false);   };      const onDragOver = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     setDrop(true);   };      const handleDrop = (e: React.DragEvent&lt;HTMLElement>) => {     if (disabled) return;     e.preventDefault();     const droppedFile = e.dataTransfer.files[0];     setDrop(false);        handleFile(droppedFile);   };    const handleFileChange = (event: React.ChangeEvent&lt;HTMLInputElement>) => {     handleFile(event.target.files[0]);   };    \/\/ \u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0438\u043d\u043f\u0443\u0442 \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 upload   const input = useRef&lt;HTMLInputElement>();    useImperativeHandle(ref, () => ({     \/\/ upload \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u043e\u0432, \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438     \/\/ \u044d\u0442\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0447\u0442\u043e \u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0435 \u043d\u0430 input     upload: () => input.current?.click(),     \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f abort \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0430, \u043e\u043d\u0430 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430     abort,   }));    const id = useId()   return (     &lt;div        className={cn(s.root, className)}       onDrop={handleDrop}       onDragOver={onDragOver}       onDragLeave={onDragLeave}     >       {children}       \/\/ \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441 s.drop \u0435\u0441\u043b\u0438 drop       &lt;label htmlFor={id} className={cn(s.label, overlay &amp;&amp; s.visible, drop &amp;&amp; s.drop)}>         &lt;input           ref={input}           disabled={disabled}           type=\"file\"           className={s.input}           onChange={handleFileChange}           id={id}         \/>         &lt;UploadOutlined className={s.icon} \/>       &lt;\/label>       {loading &amp;&amp; (         &lt;div className={s.loading}>           &lt;LoadingOutlined className={s.icon} \/>           &lt;ProgressIndicator progress={progress} className={s.progress} theme=\"green\" \/>           &lt;CloseCircleOutlined className={s.abort} onClick={abort} \/>         &lt;\/div>       )}     &lt;\/div>   ); });  Upload.displayName = \"Upload\";<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a<\/p>\n<pre><code class=\"javascript\">const [url, setUrl] = useState();  const uploadRef = useRef&lt;UploadRef>(); return (   &lt;div>     &lt;Upload ref={uploadRef} onUpload={setUrl}>       &lt;img src={url} alt=\"\" \/>     &lt;\/Upload>     &lt;button onClick={() => uploadRef.current.upload()}>       \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b     &lt;\/button>     &lt;button onClick={() => uploadRef.current.abort()}>       \u041f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443     &lt;\/button>   &lt;\/div> )<\/code><\/pre>\n<p>\u0412 \u0441\u0432\u043e\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u043e\u0432\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 markdown<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/775\/720\/c21\/775720c21139992b631cc77090517b80.gif\" width=\"1212\" height=\"530\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/775\/720\/c21\/775720c21139992b631cc77090517b80.gif\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2f4\/1d7\/af4\/2f41d7af4e6b4c3d07be2430b6cf2872.gif\" width=\"1212\" height=\"578\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2f4\/1d7\/af4\/2f41d7af4e6b4c3d07be2430b6cf2872.gif\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/140\/944\/6f1\/1409446f1d9388dc61c0bd531522fcb8.gif\" width=\"1212\" height=\"580\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/140\/944\/6f1\/1409446f1d9388dc61c0bd531522fcb8.gif\"\/><\/figure>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b, \u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438, \u043d\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u044d\u0442\u043e \u043d\u0430 \u0432\u0430\u0448\u0435 \u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u0438\u0435, \u043f\u043e\u0442\u043e\u043c\u0443 \u043a\u0430\u043a \u043d\u0438\u0447\u0435\u0433\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0430\u043c \u043d\u0435\u0442.<\/p>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044e, \u0447\u0442\u043e \u0434\u043e\u0447\u0438\u0442\u0430\u043b\u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0438 \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u044d\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439.<\/p>\n<p>\u0410 \u0432 \u043f\u0440\u0435\u0434\u0434\u0432\u0435\u0440\u0438\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0442\u043e\u043a\u0430 \u043a\u0443\u0440\u0441\u0430 <strong>React.js Developer<\/strong> \u0445\u043e\u0447\u0443 \u043f\u0440\u0438\u0433\u043b\u0430\u0441\u0438\u0442\u044c \u0432\u0430\u0441 \u043d\u0430 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435 \u043c\u0435\u0440\u043e\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u043f\u0440\u043e <a href=\"https:\/\/otus.pw\/tkTt\/\">\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/a>, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e <a href=\"https:\/\/otus.pw\/vugc\/\">\u0445\u0443\u043a\u0438 \u0438 \u043c\u0435\u043c\u043e\u0438\u0437\u0430\u0446\u0438\u044e<\/a>. \u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0439\u0442\u0435\u0441\u044c, \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/770212\/\"> https:\/\/habr.com\/ru\/articles\/770212\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438<\/p>\n<\/li>\n<li>\n<p>Drag and drop<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043d\u0430\u0448\u0435\u0439 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0435\u0440\u0442\u043a\u043e\u0439 \u0438 \u0441\u0430\u043c \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b, \u043d\u043e, \u044f \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u043f\u0440\u0438\u0435\u043c\u044b \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0438 \u0435\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432 \u043d\u0435\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 &#8212; \u043b\u0435\u0433\u043a\u043e \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u0441\u044c. \u041f\u0440\u0438 \u043d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0430 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0431\u0443\u0434\u044c \u044d\u0442\u043e \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430, \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435, \u043f\u043e\u043b\u0435 \u0441 \u0442\u0435\u043a\u0441\u0442\u043e\u043c \u0438\u043b\u0438 \u0432\u0441\u0435 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e, \u043f\u043e\u0432\u0435\u0440\u0445 \u044d\u0442\u043e\u0433\u043e \u0432\u0441\u0435\u0433\u043e \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0447\u0442\u043e \u0434\u0430\u0441\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u043e\u043d\u044f\u0442\u044c &#8212; \u0437\u0434\u0435\u0441\u044c \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0443. \u041f\u043e \u044d\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u043e.<\/p>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"javascript\">const [url, setUrl] = useState();  return (   &lt;div>     &lt;Upload onUpload={setUrl}>       &lt;img src={url} alt=\"\" \/>     &lt;\/Upload>   &lt;\/div> )<\/code><\/pre>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ref \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043c\u0435\u0442\u043e\u0434 upload, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u043e\u043a\u043d\u043e \u0441 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<pre><code class=\"javascript\">const [url, setUrl] = useState();  const uploadRef = useRef(); return (   &lt;div>     &lt;Upload ref={uploadRef} onUpload={setUrl}>       &lt;img src={url} alt=\"\" \/>     &lt;\/Upload>     &lt;button onClick={() => uploadRef.current.upload()}>       \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b     &lt;\/button>   &lt;\/div> )<\/code><\/pre>\n<p>\u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u043e\u0432\u0435\u0441\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b, \u0431\u0443\u0434\u044c \u0442\u043e \u043a\u043d\u043e\u043f\u043a\u0430, \u0438\u043a\u043e\u043d\u043a\u0430, \u0438\u043b\u0438 \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u0435\u0449\u0435.<\/p>\n<h2>Upload \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c input \u0441 \u0442\u0438\u043f\u043e\u043c file<\/p>\n<pre><code class=\"javascript\">const Upload = () => &lt;input type=\"file\" \/><\/code><\/pre>\n<figure class=\"\"><\/figure>\n<p>\u0421\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0438\u043d\u043f\u0443\u0442 &#8212; \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e, \u043c\u044b \u043f\u043e\u0439\u0434\u0435\u043c \u043f\u043e \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 &#8212; <strong>\u0441\u043a\u0440\u043e\u0435\u043c \u0438\u043d\u043f\u0443\u0442<\/strong> \u0441\u043e\u0432\u0441\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>display: none<\/strong>, \u0430 \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0434\u0440\u0443\u0433\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b. \u0427\u0442\u043e\u0431\u044b \u043a\u0430\u043a-\u0442\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0438\u043d\u0443\u0442\u043e\u043c, \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0435\u0433\u043e \u0432 label \u0442\u0435\u0433, \u043b\u044e\u0431\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 label \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 input.<\/p>\n<pre><code class=\"javascript\">const Upload = () => (   &lt;label>     &lt;input type=\"file\" \/>   &lt;\/label> )<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0445\u0443\u043a\u043e\u043c useId, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 id \u0438 \u0441\u0432\u044f\u0437\u0430\u0442\u044c label \u0438 input. \u0421\u0442\u0440\u043e\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u043e \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0448\u0430\u0433, \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c input \u0432 label \u0443\u0436\u0435 \u0441\u0432\u044f\u0436\u0435\u0442 \u044d\u0442\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043e\u0434\u043d\u0430\u043a\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u043a\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e id.<\/p>\n<pre><code class=\"javascript\">const Upload = () => {   const id = useId()   return (     &lt;label htmlFor={id}>       &lt;input type=\"file\" id={id} \/>     &lt;\/label>   ) }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u0430\u043a \u0443\u0433\u043e\u0434\u043d\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c label, \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c <strong>\u043d\u0443\u0436\u043d\u043e<\/strong> \u0431\u0443\u0434\u0435\u0442 <strong>\u0437\u0430\u0434\u0430\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443 <\/strong>\u0438<strong> \u0432\u044b\u0441\u043e\u0442\u0443<\/strong>, \u043d\u0443 \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e \u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 label \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u043a\u043e\u0448\u043a\u043e \u0441 \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0444\u0430\u0439\u043b\u043e\u0432. \u0421\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441\u043e \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u0432 \u043a\u043e\u043d\u0446\u0435, \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u0432\u043b\u0435\u043a\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u044e. \u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043c\u0441\u044f \u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<h2>Upload \u0444\u0443\u043d\u043a\u0446\u0438\u044f. \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440<\/h2>\n<h3>\u0410\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438 \u0442\u0438\u043f\u044b<\/h3>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0447\u0438\u0441\u0442\u043e\u0439 \u0438 \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u0430 \u043e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0447\u0443\u0439\u043a\u043e\u0439 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u043c\u043e\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043a\u0430\u043a\u0438\u043c-\u0442\u043e \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440. \u041c\u043e\u0436\u043d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <a href=\"https:\/\/github.com\/axios\/axios\">axios<\/a> \u0438 \u0435\u0441\u043b\u0438 \u0432 \u0432\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u043e\u043d \u0443\u0436\u0435 \u0435\u0441\u0442\u044c &#8212; \u0442\u043e \u043e\u0442\u043b\u0438\u0447\u043d\u043e, \u0435\u0441\u043b\u0438 \u0436\u0435 \u043d\u0435\u0442, \u043f\u0440\u0438\u043a\u0440\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0440\u0430\u0434\u0438 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f &#8212; \u0442\u0430\u043a\u0430\u044f \u0441\u0435\u0431\u0435 \u0438\u0434\u0435\u044f. \u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e XMLHttpRequest, \u043a\u0441\u0442\u0430\u0442\u0438 \u0442\u043e\u0442 \u0436\u0435 axios \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f upload \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c file, url, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u043f\u0446\u0438\u0439. \u041f\u0443\u0441\u0442\u044c \u0432 \u043d\u0430\u0448\u0435\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0432 \u044d\u0442\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f onProgress, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u043d\u0442, \u043d\u0430 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(   file: File,   url: string,   options?: { onProgress?: (progress: number) => void } ): Promise&lt;T> => {}<\/code><\/pre>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u0438\u043c\u0435\u043d\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0440\u0435\u0442\u044c\u0435\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430? \u042d\u0442\u043e \u043e\u043f\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0441\u0442\u0438\/\u0437\u0430\u043a\u0440\u044b\u0442\u043e\u0441\u0442\u0438 \u0438 \u043a\u043d\u0438\u0433\u0443 &#171;<a href=\"https:\/\/www.litres.ru\/book\/robert-s-martin\/chistyy-kod-sozdanie-analiz-i-refaktoring-pdf-epub-6444478\/\">\u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434<\/a>&#171;.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 3-\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u044d\u0442\u043e \u043f\u043e\u0447\u0435\u0440\u043f\u043d\u0443\u0442\u043e \u0438\u0437 \u043a\u043d\u0438\u0433\u0438 &#171;\u0447\u0438\u0441\u0442\u044b\u0439 \u043a\u043e\u0434&#187;. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u043d\u0435 \u043f\u0440\u0435\u0432\u044b\u0448\u0430\u0442\u044c &#171;\u043a\u0432\u043e\u0442\u0443&#187;, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 &#171;\u0437\u0430\u043a\u0440\u044b\u0442\u0430&#187; \u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c, \u043d\u043e &#171;\u043e\u0442\u043a\u0440\u044b\u0442\u0430&#187; \u043a \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u043c, \u043c\u044b \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0441\u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u043f\u0446\u0438\u044e \u0438 \u044d\u0442\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u0441\u043b\u043e\u043c\u0430\u0435\u0442 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434. <\/p>\n<p>\u0415\u0449\u0435 \u0445\u043e\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u043e\u0442 \u044d\u0442\u0443 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044e <code>upload = &lt;T>(): Promise&lt;T><\/code><\/p>\n<p>\u042d\u0442\u043e \u0434\u0436\u0435\u043d\u0435\u0440\u0438\u043a, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0430\u0448\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0435\u0440\u043d\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f, \u0442\u043e\u0447\u043d\u0435\u0435 \u043f\u0440\u043e\u043c\u0438\u0441 (\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0442\u0438\u043f\u043e\u043c.<\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<p>\u0421 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438\u0441\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u0441 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043a\u0443\u0445\u043d\u0435\u0439.<\/p>\n<h3>\u0417\u0430\u043f\u0440\u043e\u0441 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e XMLHttpRequest<\/h3>\n<p>\u0411\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c XMLHttpRequest, \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u043d\u0438\u043c \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 4 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0448\u0430\u0433\u0430:<\/p>\n<ol>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 XMLHttpRequest<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"javascript\">\/\/ \u0428\u0430\u0433 1 \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 XMLHttprequest const xhr = new XMLHttpRequest();  \/\/ \u0428\u0430\u0433 2 \u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 xhr.open('POST', url);  \/\/ \u0428\u0430\u0433 3 \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 xhr.onload = () => {   if (xhr.status === 200) {     \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430   } else {     \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a   } };  \/\/ \u0428\u0430\u0433 4 \u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 xhr.send(myData);<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0441 fetch, \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0431\u043e\u043b\u0435\u0435 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u0439, \u043e\u0434\u043d\u0430\u043a\u043e \u043e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0437\u043d\u0430\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u044b\u043b\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e, \u0447\u0435\u043c \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0445\u0432\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f fetch \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e abort \u0434\u043b\u044f \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<p>\u0417\u0430\u0432\u0435\u0440\u043d\u0435\u043c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432 \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e. \u041e\u0431\u0440\u0430\u0449\u0430\u044e \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0444\u0443\u043d\u043a\u0446\u0438\u044f upload \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u043c\u0438\u0441 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u043c \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u043e\u043c, \u0442\u043e \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438 then, catch, finally, \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u0442\u043e\u043d \u0434\u043b\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432, \u043d\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e\u0435 api.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);          xhr.onload = () => {       if (xhr.status === 200) {         \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430         resolve(\/* \u0441\u044e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 *\/)       } else {         \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0448\u0438\u0431\u043e\u043a         reject(\/* \u0441\u044e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u043e\u0448\u0438\u0431\u043a\u0443 *\/)       }     };          xhr.send(myData);   }) }<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u043f\u0440\u043e\u043c\u0438\u0441\u0430\u043c\u0438, \u0442\u043e \u0432 \u0434\u0432\u0443\u0445 \u0441\u043b\u043e\u0432\u0430\u0445 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const fn = () => new Promise((resolve, reject) => {   \/\/ \u041d\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0430\u043a\u0430\u0434\u0435\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440   resolve(data); \/\/ \u0422\u043e \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 resolve \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 .then()   reject(error); \/\/ \u0422\u043e \u0447\u0442\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0432 reject \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 .catch() });  fn().then(data => {}).catch(error => {});<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b.<\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u0444\u0430\u0439\u043b\u0430<\/h3>\n<p>\u041d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043a\u0430\u043a \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b, \u0447\u0430\u0441\u0442\u043e \u043c\u044b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0442\u0435\u043a\u0441\u0442 \u0432 json \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Content-Type \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 \u0444\u0430\u0439\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/API\/FormData\">FormData<\/a> \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 append \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u043d\u0435\u0433\u043e \u0444\u0430\u0439\u043b \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e, \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a Content-Type \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438.<\/p>\n<pre><code class=\"javascript\">\/\/ \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 const myData = new FormData(); \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u0441 \u043a\u043b\u044e\u0447\u043e\u043c 'my_file', \u0442\u0443\u0442 \u0432\u0430\u0436\u043d\u044b\u0439 \u043d\u044e\u0430\u043d\u0441, \u043e\u0431 \u044d\u0442\u043e\u043c \u043d\u0438\u0436\u0435 myData.append('my_file' \/* &lt;- \u044d\u0442\u043e \u043a\u043b\u044e\u0447 *\/, file);  \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u0430\u0439\u043b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 xhr.send(myData);<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e, \u043d\u0430\u0434\u043e \u0442\u043e\u0447\u043d\u043e \u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u043e\u0439 \u043a\u043b\u044e\u0447 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c. \u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u044f \u0443\u043a\u0430\u0437\u0430\u043b \u043a\u043b\u044e\u0447 <code>\"my_file\"<\/code>, \u043e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u0442\u0430\u043a \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 express.js (\u0431\u0435\u043a\u0435\u043d\u0434)<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u0430 express.js \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"javascript\">const app = express();  app.post('\/upload', (request, response) => {   const file = request.files.my_file; \/\/ &lt;- \u00a0\u0432\u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430   \/\/ \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0444\u0430\u0439\u043b\u0430   \/\/ ...   \/\/ \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435   \/\/ ...   \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435    \/\/ ...   \/\/ \u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c url \u0444\u0430\u0439\u043b\u0430   response.send({ url: file_url }) });<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421 \u0443\u0447\u0435\u0442\u043e\u043c \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0444\u0430\u0439\u043b\u0430, \u0444\u0443\u043d\u043a\u0446\u0438\u044f upload \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);          xhr.onload = () => {       if (xhr.status === 200) {         resolve(\/*  *\/)       } else {         reject(\/*  *\/)       }     };      \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0443 \u0444\u0430\u0439\u043b\u0430     const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) }<\/code><\/pre>\n<h3>\u041f\u0440\u043e\u0433\u0440\u0435\u0441\u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440<\/h3>\n<p>\u0423 XMLHttpRequest \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e upload, \u0438 \u043d\u0430 \u044d\u0442\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0441\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a onprogress, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0439\u0442. \u042d\u0442\u0443 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 onProgress \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430.<\/p>\n<pre><code class=\"javascript\">xhr.upload.onprogress = (event) => {   \/\/ event.total - \u043e\u0431\u0449\u0438\u0439 \u0432\u0435\u0441 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0431\u0430\u0439\u0442\u0430\u0445   \/\/ event.loaded - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u0431\u0430\u0439\u0442   \/\/ Math.round((event.loaded \/ event.total) * 100) - \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043e\u0442 1 \u0434\u043e 100   onProgress(Math.round((event.loaded \/ event.total) * 100)); };<\/code><\/pre>\n<p>\u0421 \u044d\u0442\u0438\u043c \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   \/\/ \u0414\u043e\u0441\u0442\u0430\u043b\u0438 onProgress \u0438\u0437 options   const onProgress = options?.onProgress;   return new Promise((resolve, reject) => {     const xhr = new XMLHttpRequest();     xhr.open('POST', url);      \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430     xhr.upload.onprogress = (event) => {       onProgress?.(Math.round((event.loaded \/ event.total) * 100));     };          xhr.onload = () => {       if (xhr.status === 200) {         resolve(\/*  *\/)       } else {         reject(\/*  *\/)       }     };      const myData = new FormData();     myData.append('my_file', file);          xhr.send(myData);   }) }<\/code><\/pre>\n<h3>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 XMLHttpRequest \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u0430, \u0432 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0436\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f json \u043a\u0430\u043a \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u043e \u044d\u0442\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u043e\u0442\u0432\u0435\u0442\u043e\u0432 json: <code>xhr.responseType = 'json'<\/code><\/p>\n<p>\u0422\u0430\u043a \u0432 <code>xhr.response<\/code> \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0443\u0436\u0435 \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0435\u043d\u043d\u044b\u0439 json, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043c <code>xhr.response<\/code> \u0432 <code>resolve<\/code> \u0438 <code>reject<\/code>.<\/p>\n<pre><code class=\"javascript\">export const upload = &lt;T>(file: File, url: string, options?: { onProgress?: (progress: number) => void }): Promise&lt;T> => {   const onProgress = options?.onProgress;   return new Promise((resolve, reject) => {     const xhr = new<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-358633","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/358633","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=358633"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/358633\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=358633"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=358633"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=358633"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}