# frozen_string_literal: truerequire"fileutils"require"pathname"require"digest/md5"require"active_support/core_ext/numeric/bytes"moduleActiveStorage# Wraps a local disk path as an Active Storage service. See ActiveStorage::Service for the generic API# documentation that applies to all services.classService::DiskService<Serviceattr_reader:rootdefinitialize(root:)@root=rootenddefupload(key,io,checksum: nil)instrument:upload,key: key,checksum: checksumdoIO.copy_stream(io,make_path_for(key))ensure_integrity_of(key,checksum)ifchecksumendenddefdownload(key)ifblock_given?instrument:streaming_download,key: keydoFile.open(path_for(key),"rb")do|file|whiledata=file.read(64.kilobytes)yielddataendendendelseinstrument:download,key: keydoFile.binreadpath_for(key)endendenddefdownload_chunk(key,range)instrument:download_chunk,key: key,range: rangedoFile.open(path_for(key),"rb")do|file|file.seekrange.beginfile.readrange.sizeendendenddefdelete(key)instrument:delete,key: keydobeginFile.deletepath_for(key)rescueErrno::ENOENT# Ignore files already deletedendendenddefdelete_prefixed(prefix)instrument:delete_prefixed,prefix: prefixdoDir.glob(path_for("#{prefix}*")).eachdo|path|FileUtils.rm_rf(path)endendenddefexist?(key)instrument:exist,key: keydo|payload|answer=File.exist?path_for(key)payload[:exist]=answeranswerendenddefurl(key,expires_in:,filename:,disposition:,content_type:)instrument:url,key: keydo|payload|verified_key_with_expiration=ActiveStorage.verifier.generate(key,expires_in: expires_in,purpose: :blob_key)generated_url=url_helpers.rails_disk_service_url(verified_key_with_expiration,host: current_host,filename: filename,disposition: content_disposition_with(type: disposition,filename: filename),content_type: content_type)payload[:url]=generated_urlgenerated_urlendenddefurl_for_direct_upload(key,expires_in:,content_type:,content_length:,checksum:)instrument:url,key: keydo|payload|verified_token_with_expiration=ActiveStorage.verifier.generate({key: key,content_type: content_type,content_length: content_length,checksum: checksum},{expires_in: expires_in,purpose: :blob_token})generated_url=url_helpers.update_rails_disk_service_url(verified_token_with_expiration,host: current_host)payload[:url]=generated_urlgenerated_urlendenddefheaders_for_direct_upload(key,content_type:,**){"Content-Type"=>content_type}endprivatedefpath_for(key)File.joinroot,folder_for(key),keyenddeffolder_for(key)[key[0..1],key[2..3]].join("/")enddefmake_path_for(key)path_for(key).tap{|path|FileUtils.mkdir_pFile.dirname(path)}enddefensure_integrity_of(key,checksum)unlessDigest::MD5.file(path_for(key)).base64digest==checksumdeletekeyraiseActiveStorage::IntegrityErrorendenddefurl_helpers@url_helpers||=Rails.application.routes.url_helpersenddefcurrent_hostActiveStorage::Current.hostendendend