S3 рдореЗрдВ рдорд▓реНрдЯреАрдереНрд░реЗрдбреЗрдб рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб

рдпрд╣ рд▓реЗрдЦ рдЕрдореЗрдЬрди S3 рдореЗрдВ рдордгрд┐ aws-sdk рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рд░реВрдмреА рдореЗрдВ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрдкрдпреЛрдЧ рдФрд░ рдкреНрд░рджрд░реНрд╢рди рд▓рд╛рдн рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИред

рдПрдХ рд╕рд░рд▓ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ


рдЖрдзрд┐рдХрд╛рд░рд┐рдХ (рдпрд╛рдиреА, рдЕрдореЗрдЬрд╝реЕрди рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд) рд░рддреНрди aws-sdk рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рдпрджрд┐ рдЖрдк Amazon Web Services (AWS) рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рднрд╛рдЧ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рдХреЛрдб рдореЗрдВ рддреАрди рд▓рд╛рдЗрдиреЗрдВ рд╣реЛрддреА рд╣реИрдВ:
def upload_to_s3(config, src, dst) #     S3,      config s3 = AWS::S3.new( :access_key_id => config['access_key_id'], :secret_access_key => onfig['secret_access_key']) #  ,    'dst'  S3 (   ) s3_file = s3.buckets[config['bucket_name']].objects[dst] #    src    (   ) s3_file.write(:file => src, :acl => :public_read) end 

рд╡рд┐рдзрд┐ рдХрд╛рдо рдХрд░рддреА рд╣реИ рдФрд░ 5 рдПрдордмреА (рдЫреЛрдЯреА рдлрд╛рдЗрд▓реЛрдВ рдкрд░, рдФрд╕рдд рдЧрддрд┐ рдбреНрд░реЙрдк) рд╕реЗ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ 5 рдПрдордмреА / рдПрд╕ рддрдХ рдХреА рдФрд╕рдд рдбрд╛рдЙрдирд▓реЛрдб рдЧрддрд┐ рджрд┐рдЦрд╛рддреА рд╣реИред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреНрд░рдпреЛрдЧреЛрдВ рд╕реЗ рдпрд╣ рдиреЛрдЯрд┐рд╕ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рдПрдХ рд╕рд╛рде рдХрдИ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдХреБрд▓ рдЧрддрд┐ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЧрддрд┐ рд╕реЗ рдЕрдзрд┐рдХ рд╣реИред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рдкреНрд░рддрд┐ рд╕реНрдЯреНрд░реАрдо рдмреИрдВрдбрд╡рд┐рдбреНрде рд╕реАрдорд╛ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреА рд╣реИ? рдЖрдЗрдП рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдФрд░ рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ_рдЕрдкрд▓реЛрдб рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд╛рдЙрдирд▓реЛрдб рдХреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ, рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред

рднрд╛рдЧреЛрдВ рдореЗрдВ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ


Aws-sdk рдореЗрдВ рднрд╛рдЧреЛрдВ рдореЗрдВ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ multipart_upload рд╡рд┐рдзрд┐ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдЗрд╕рдХреА рдЦрд╛рд╕рд┐рдпрдд:
 def multipart_upload_to_s3(src, dst, config) s3 = AWS::S3.new( :access_key_id => config['access_key_id'], :secret_access_key => onfig['secret_access_key']) s3_file = s3.buckets[config['bucket_name']].objects[dst] #   src    src_io = File.open(src, 'rb') #    read_size = 0 uploaded_size = 0 parts = 0 #    src_size = File.size(src) #    s3_file = s3_file.multipart_upload({:acl => :public_read}) do |upload| while read_size < src_size #          buff = src_io.readpartial(config['part_size']) #   read_size += buff.size part_number = parts += 1 # ,     S3 upload.add_part :data => buff, :part_number => part_number end end #    src_io.close s3_file end 

рдпрд╣ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдбрд╛рдЙрдирд▓реЛрдб рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд▓рдЧрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдирдИ рд╡рд┐рдзрд┐ рдХреЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд▓рд╛рдн рд╣реИрдВ:

рдпреЗ рджреЛ рдЧреБрдг рд╣рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддреЗ рд╕рдордп рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред

рднрд╛рдЧреЛрдВ рдореЗрдВ рдЧреБрдгрд╛ рдлрд╝рд╛рдЗрд▓ рдбрд╛рдЙрдирд▓реЛрдб


рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИрдВ:

рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдпрд╣ рдорд┐рд╢реНрд░рд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ рдЬреЛ рд╕рдмрд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐:

рдпрд╣рд╛рдБ рдорд▓реНрдЯреАрдереНрд░реЗрдб рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдб рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╣реИ:
 def threaded_upload_to_s3(src, dst, config) s3 = AWS::S3.new( :access_key_id => config['access_key_id'], :secret_access_key => onfig['secret_access_key']) s3_file = s3.buckets[config['bucket_name']].objects[dst] src_io = File.open(src, 'rb') read_size = 0 uploaded_size = 0 parts = 0 src_size = File.size(src) s3_file = s3_file.multipart_upload({:acl => :public_read}) do |upload| #        upload_threads = [] #   ( ),   тАЬтАЭ mutex = Mutex.new max_threads = [config['threads_count'], (src_size.to_f / config['part_size']).ceil].min #       max_threads.times do |thread_number| upload_threads << (Thread.new do #     while true #    ,         #   mutex.lock #  ,        break unless read_size < src_size #          buff = src_io.readpartial(config['part_size']) #   read_size += buff.size part_number = parts += 1 #   mutex.unlock # ,     S3 upload.add_part :data => buff, :part_number => part_number end end) end #      upload_threads.each{|thread| thread.join} end src_io.close s3_file end 

рдзрд╛рдЧреЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдорд╛рдирдХ рдереНрд░реЗрдб рдХреНрд▓рд╛рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ (рд░реВрдмреА рдореЗрдВ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдЖрд▓реЗрдЦ habrahabr.ru/post/94574 рдореЗрдВ рд╡рд░реНрдгрд┐рдд рд╣реИрдВ)ред рдЖрдкрд╕реА рдЕрдкрд╡рд╛рджреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдорд╛рдирдХ рдореНрдпреВрдЯреЗрдХреНрд╕ рд╡рд░реНрдЧ рджреНрд╡рд╛рд░рд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рд╕рд░рд▓рддрдо рдмрд╛рдЗрдирд░реА рд╕реЗрдорд╛рдлреЛрд░ (рдореНрдпреВрдЯреЗрдХреНрд╕) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рд╕реЗрдорд╛рдлреЛрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ? рдЙрдирдХреА рдорджрдж рд╕реЗ, рд╣рдо рдХреЛрдб рдХреЗ рдПрдХ рдЦрдВрдб рдХреЛ рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдЬрд┐рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ) рдЬреЛ рдХреЗрд╡рд▓ рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдзрд╛рдЧреЗ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИред рд╢реЗрд╖ рдереНрд░реЗрдбреНрд╕ рдХреЛ рддрдм рддрдХ рдЗрдВрддрдЬрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬрдм рддрдХ рдХрд┐ рд╕реЗрдорд╛рдлреЛрд░ рдкрд░ рдереНрд░реЗрдб рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЦрдВрдб рдХреЛ рдЫреЛрдбрд╝ рдирд╣реАрдВ рджреЗрддрд╛ред рдЖрдорддреМрд░ рдкрд░, рдЕрд░реНрдз-рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рд╛рдЭрд╛ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рддрдХ рдЙрдЪрд┐рдд рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рд╛рдорд╛рдиреНрдп рд╕рдВрд╕рд╛рдзрди рд╣реИрдВ: рдЗрдирдкреБрдЯ рдСрдмреНрдЬреЗрдХреНрдЯ src_io рдФрд░ рдЪрд░ read_size рдФрд░ рднрд╛рдЧреЛрдВред рдмрдлрд╝рд░ рдФрд░ part_number рдЪрд░ рдереНрд░реЗрдб рдХреЗ рднреАрддрд░ рд╕реНрдерд╛рдиреАрдп рдШреЛрд╖рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ (рдпрд╛рдиреА, рдереНрд░реЗрдб.рдиреНрдпреВ рдбреВ ... рдПрдВрдб рдмреНрд▓реЙрдХ) рдФрд░ рдЗрд╕рд▓рд┐рдП рд╕рд╛рдЭрд╛ рдирд╣реАрдВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред

рдЖрдк рд▓реЗрдЦ www.tutorialspoint.com/ruby/ruby_multithreading.htm рдореЗрдВ рд░реВрдмреА рдореЗрдВ рд╕реЗрдорд╛рдлреЛрд░ рдФрд░ рдорд▓реНрдЯреАрдереНрд░реЗрдбрд┐рдВрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ

рддреБрд▓рдирд╛ рдкрд░рд┐рдгрд╛рдо


рд╣рдо рдХрдИ рдкрд░реАрдХреНрд╖рдг рдлрд╝рд╛рдЗрд▓реЛрдВ (1 рдПрдордмреА, 10 рдПрдордмреА, 50 рдПрдордмреА, 150 рдПрдордмреА рдЖрдХрд╛рд░ рдореЗрдВ) рдкрд░ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбрд╛рдЙрдирд▓реЛрдб рдЧрддрд┐ рдХреЛ рдорд╛рдкрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
рдлрд╝рд╛рдЗрд▓

рднрд╛рдЧреЛрдВ

рдзрд╛рд░рд╛рдУрдВ

рдЕрдкрд▓реЛрдб, рдПрдордмреА / рдПрд╕

multipart_upload, Mb / s

рдкрд┐рд░реЛрдпрд╛_рдЕрдкрд▓реЛрдб, рдПрдордмреА / рдПрд╕

1

64k

1

1

0.78

0.29 (37%)

0.29 (37%)

2

512K

1

1

2.88

1.84 (64%)

1.65 (57%)

3

1 рдПрдордмреА

1

1

3.39

2.38 (70%)

2.58 (76%)

4

10 рдПрдордмреА

2

2

5.06

4.50 (89%)

7.69 (152%)

5

50 рдПрдордмреА

10

5

4.48

4.41 (98%)

9.02 (201%)

6

50 рдПрдордмреА

10

10

4.33

4.44 (103%)

8.49 (196%)

7

150MB

30

5

4.34

4.43 (102%)

9.22 (212%)

8

150MB

30

10

4.48

4.52 (101%)

8.90 (199%)


рдЙрд╕реА рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдпреВрд░реЛрдкреАрдп рд╕рдВрдШ рдкрд╢реНрдЪрд┐рдо (рдЖрдпрд░рд▓реИрдВрдб) рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдПрд╕ 3 рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд▓рд┐рдП рдПрдХ рдорд╢реАрди рд╕реЗ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП 10 рдЕрдиреБрдХреНрд░рдорд┐рдХ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред
рдпрджрд┐ рд╣рдо 4-8 рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рджрд░ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдорд╛рдк рддреНрд░реБрдЯрд┐ рд▓рдЧрднрдЧ 8% рд╣реИ, рдЬреЛ рдХрд╛рдлреА рд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИред
рдЫреЛрдЯреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ рднрд╛рдЧреЛрдВ (рдорд▓реНрдЯреАрдкрд╛рд░реНрдЯ_рдкреБрд▓реЛрдб) рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рд╕рд░рд▓ рдФрд░ рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рд╕рдмрд╕реЗ рдЦрд░рд╛рдм рдкрд░рд┐рдгрд╛рдо рджрд┐рдЦрд╛ред
рдорд▓реНрдЯреАрдереНрд░реЗрдбреЗрдб рдбрд╛рдЙрдирд▓реЛрдб (рдереНрд░реЗрдбреЗрдб_рдЙрдкрд▓реЛрдб) рдиреЗ рдПрдХ рднрд╛рдЧ рд╕реЗ рдлрд╛рдЗрд▓реЛрдВ рдкрд░ рдЙрд╕реА рддрд░рд╣ рдХреА рджрдХреНрд╖рддрд╛ рджрд┐рдЦрд╛рдИ рдЬреИрд╕реЗ рдХрд┐ рднрд╛рдЧреЛрдВ рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб (рдЬреЛ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд╣реИ)ред рд▓реЗрдХрд┐рди рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд▓рд╛рдн рд╣реИ - рджреЛ рдмрд╛рд░ рддрдХ (рд╕рд╛рдорд╛рдиреНрдп рдбрд╛рдЙрдирд▓реЛрдб рдХреА рддреБрд▓рдирд╛ рдореЗрдВ)ред
рднрд╛рдЧ рдХреЗ рдЗрд╖реНрдЯрддрдо рдЖрдХрд╛рд░ рдФрд░ рдзрд╛рд░рд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдХрд╛рд░реНрдп рдирд╣реАрдВ рдереЗ, рд▓реЗрдХрд┐рди рдмрдбрд╝реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ 5 рд╕реЗ 10 рддрдХ рдХреА рдзрд╛рд░рд╛рдУрдВ рдХреЛ рдмрдврд╝рд╛рдиреЗ рд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рднрд╛рд╡ рдирд╣реАрдВ рд╣реБрдЖред

рдирд┐рд╖реНрдХрд░реНрд╖


рдорд▓реНрдЯреАрдкреНрд░реЗрдбреЗрдб рдлрд╝рд╛рдЗрд▓ рдЕрдкрд▓реЛрдбрд┐рдВрдЧ рдЙрди рдлрд╛рдЗрд▓реЛрдВ рдкрд░ рд╕рд╛рдорд╛рдиреНрдп рд╕реЗ рдЕрдзрд┐рдХ рдкреНрд░рднрд╛рд╡реА рд╕рд╛рдмрд┐рдд рд╣реБрдИ, рдЬрд┐рдирдореЗрдВ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рднрд╛рдЧ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ, рдЧрддрд┐ рдореЗрдВ рд╡реГрджреНрдзрд┐ - рджреЛ рдЧреБрдирд╛ рддрдХред
рд╡реИрд╕реЗ, рдпрд╣ рдПрдХ рдРрд╕реА рд╡рд┐рдзрд┐ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛрдЧрд╛ рдЬреЛ рдлрд╝рд╛рдЗрд▓ рдЖрдХрд╛рд░ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рдбрд╛рдЙрдирд▓реЛрдб рд╡рд┐рдзрд┐ рдЪреБрдирддреА рд╣реИред
рдЙрджрд╛рд╣рд░рдгреЛрдВ рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб Github: github.com/whisk/s3up рдкрд░ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ

Source: https://habr.com/ru/post/In140940/


All Articles