[{"data":1,"prerenderedAt":1551},["ShallowReactive",2],{"navigation_docs_en":3,"-en-storage-disk-api":448,"-en-storage-disk-api-surround":1546},[4,45,120,157,173,203,233,259,271,287,307,326,339,356,373,386,398,425],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":44},"Getting Started","i-lucide-rocket","\u002Fen\u002Fgetting-started","en\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F01.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F01.getting-started\u002F2.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Your first module","\u002Fen\u002Fgetting-started\u002Ffirst-module","en\u002F01.getting-started\u002F3.first-module","i-lucide-package-plus",{"title":26,"path":27,"stem":28,"icon":29},"Project structure","\u002Fen\u002Fgetting-started\u002Fproject-structure","en\u002F01.getting-started\u002F4.project-structure","i-lucide-folder-tree",{"title":31,"path":32,"stem":33,"icon":34},"The shop sample application","\u002Fen\u002Fgetting-started\u002Fsample-app","en\u002F01.getting-started\u002F5.sample-app","i-lucide-shopping-cart",{"title":36,"path":37,"stem":38,"icon":39},"Coming from Laravel","\u002Fen\u002Fgetting-started\u002Fcoming-from-laravel","en\u002F01.getting-started\u002F6.coming-from-laravel","i-lucide-arrow-right-left",{"title":41,"path":42,"stem":43,"icon":39},"Coming from Symfony","\u002Fen\u002Fgetting-started\u002Fcoming-from-symfony","en\u002F01.getting-started\u002F7.coming-from-symfony",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"CLI Reference","i-lucide-terminal","\u002Fen\u002Fcli","en\u002F02.cli",[51,55,60,65,70,75,80,85,90,95,100,105,110,115],{"title":52,"path":53,"stem":54,"icon":47},"Overview","\u002Fen\u002Fcli\u002Foverview","en\u002F02.cli\u002F1.overview",{"title":56,"path":57,"stem":58,"icon":59},"add compose \u002F add docker","\u002Fen\u002Fcli\u002Fadd-compose","en\u002F02.cli\u002F10.add-compose","i-lucide-container",{"title":61,"path":62,"stem":63,"icon":64},"add mail","\u002Fen\u002Fcli\u002Fadd-mail","en\u002F02.cli\u002F11.add-mail","i-lucide-mail-plus",{"title":66,"path":67,"stem":68,"icon":69},"add notification","\u002Fen\u002Fcli\u002Fadd-notification","en\u002F02.cli\u002F12.add-notification","i-lucide-bell-plus",{"title":71,"path":72,"stem":73,"icon":74},"add realtime","\u002Fen\u002Fcli\u002Fadd-realtime","en\u002F02.cli\u002F13.add-realtime","i-lucide-radio-tower",{"title":76,"path":77,"stem":78,"icon":79},"add seeder","\u002Fen\u002Fcli\u002Fadd-seeder","en\u002F02.cli\u002F14.add-seeder","i-lucide-sprout",{"title":81,"path":82,"stem":83,"icon":84},"new project","\u002Fen\u002Fcli\u002Fnew-project","en\u002F02.cli\u002F2.new-project","i-lucide-folder-plus",{"title":86,"path":87,"stem":88,"icon":89},"new module","\u002Fen\u002Fcli\u002Fnew-module","en\u002F02.cli\u002F3.new-module","i-lucide-blocks",{"title":91,"path":92,"stem":93,"icon":94},"add surface","\u002Fen\u002Fcli\u002Fadd-surface","en\u002F02.cli\u002F4.add-surface","i-lucide-layers-2",{"title":96,"path":97,"stem":98,"icon":99},"add domain","\u002Fen\u002Fcli\u002Fadd-domain","en\u002F02.cli\u002F5.add-domain","i-lucide-box",{"title":101,"path":102,"stem":103,"icon":104},"add handler","\u002Fen\u002Fcli\u002Fadd-handler","en\u002F02.cli\u002F6.add-handler","i-lucide-webhook",{"title":106,"path":107,"stem":108,"icon":109},"new migration","\u002Fen\u002Fcli\u002Fnew-migration","en\u002F02.cli\u002F7.new-migration","i-lucide-file-plus",{"title":111,"path":112,"stem":113,"icon":114},"worker generators","\u002Fen\u002Fcli\u002Fworker-generators","en\u002F02.cli\u002F8.worker-generators","i-lucide-cog",{"title":116,"path":117,"stem":118,"icon":119},"add db","\u002Fen\u002Fcli\u002Fadd-db","en\u002F02.cli\u002F9.add-db","i-lucide-database-zap",{"title":121,"icon":99,"path":122,"stem":123,"children":124,"page":44},"Framework","\u002Fen\u002Fframework","en\u002F03.framework",[125,128,133,138,142,147,152],{"title":52,"path":126,"stem":127,"icon":99},"\u002Fen\u002Fframework\u002Foverview","en\u002F03.framework\u002F1.overview",{"title":129,"path":130,"stem":131,"icon":132},"Application lifecycle","\u002Fen\u002Fframework\u002Fapp","en\u002F03.framework\u002F2.app","i-lucide-power",{"title":134,"path":135,"stem":136,"icon":137},"Server","\u002Fen\u002Fframework\u002Fserver","en\u002F03.framework\u002F3.server","i-lucide-server",{"title":139,"path":140,"stem":141,"icon":114},"Worker","\u002Fen\u002Fframework\u002Fworker","en\u002F03.framework\u002F4.worker",{"title":143,"path":144,"stem":145,"icon":146},"Realtime","\u002Fen\u002Fframework\u002Frealtime","en\u002F03.framework\u002F5.realtime","i-lucide-radio",{"title":148,"path":149,"stem":150,"icon":151},"Migrations","\u002Fen\u002Fframework\u002Fmigrations","en\u002F03.framework\u002F6.migrations","i-lucide-file-stack",{"title":153,"path":154,"stem":155,"icon":156},"Social login","\u002Fen\u002Fframework\u002Fsocial-login","en\u002F03.framework\u002F7.social-login","i-lucide-log-in",{"title":158,"icon":159,"path":160,"stem":161,"children":162,"page":44},"Reference","i-lucide-book-open","\u002Fen\u002Freference","en\u002F04.reference",[163,168],{"title":164,"path":165,"stem":166,"icon":167},"Configuration","\u002Fen\u002Freference\u002Fconfiguration","en\u002F04.reference\u002F1.configuration","i-lucide-settings",{"title":169,"path":170,"stem":171,"icon":172},"External dependencies","\u002Fen\u002Freference\u002Fdependencies","en\u002F04.reference\u002F2.dependencies","i-lucide-package",{"title":174,"icon":175,"path":176,"stem":177,"children":178,"page":44},"Concepts","i-lucide-lightbulb","\u002Fen\u002Fconcepts","en\u002F05.concepts",[179,184,189,193,198],{"title":180,"path":181,"stem":182,"icon":183},"Architecture","\u002Fen\u002Fconcepts\u002Farchitecture","en\u002F05.concepts\u002F1.architecture","i-lucide-layers",{"title":185,"path":186,"stem":187,"icon":188},"Error model","\u002Fen\u002Fconcepts\u002Ferror-model","en\u002F05.concepts\u002F2.error-model","i-lucide-shield-alert",{"title":164,"path":190,"stem":191,"icon":192},"\u002Fen\u002Fconcepts\u002Fconfiguration","en\u002F05.concepts\u002F3.configuration","i-lucide-settings-2",{"title":194,"path":195,"stem":196,"icon":197},"Codegen pipeline","\u002Fen\u002Fconcepts\u002Fcodegen-pipeline","en\u002F05.concepts\u002F4.codegen-pipeline","i-lucide-file-json",{"title":199,"path":200,"stem":201,"icon":202},"Design patterns","\u002Fen\u002Fconcepts\u002Fdesign-patterns","en\u002F05.concepts\u002F5.design-patterns","i-lucide-puzzle",{"title":204,"icon":205,"path":206,"stem":207,"children":208,"page":44},"auth","i-lucide-shield-check","\u002Fen\u002Fauth","en\u002F06.auth",[209,214,219,224,229],{"title":210,"path":211,"stem":212,"icon":213},"Authentication","\u002Fen\u002Fauth\u002Foverview","en\u002F06.auth\u002F1.overview","i-lucide-key-round",{"title":215,"path":216,"stem":217,"icon":218},"RBAC","\u002Fen\u002Fauth\u002Frbac","en\u002F06.auth\u002F2.rbac","i-lucide-users",{"title":220,"path":221,"stem":222,"icon":223},"Policies","\u002Fen\u002Fauth\u002Fpolicy","en\u002F06.auth\u002F3.policy","i-lucide-gavel",{"title":225,"path":226,"stem":227,"icon":228},"Using auth standalone","\u002Fen\u002Fauth\u002Fstandalone","en\u002F06.auth\u002F4.standalone","i-lucide-plug",{"title":230,"path":231,"stem":232,"icon":156},"Social login with goth, standalone","\u002Fen\u002Fauth\u002Fsocial-standalone","en\u002F06.auth\u002F5.social-standalone",{"title":234,"icon":235,"path":236,"stem":237,"children":238,"page":44},"dbx","i-lucide-database","\u002Fen\u002Fdbx","en\u002F07.dbx",[239,242,246,250,255],{"title":52,"path":240,"stem":241,"icon":235},"\u002Fen\u002Fdbx\u002Foverview","en\u002F07.dbx\u002F1.overview",{"title":243,"path":244,"stem":245,"icon":228},"pgx","\u002Fen\u002Fdbx\u002Fpg","en\u002F07.dbx\u002F2.pg",{"title":247,"path":248,"stem":249,"icon":183},"bun","\u002Fen\u002Fdbx\u002Fbunx","en\u002F07.dbx\u002F3.bunx",{"title":251,"path":252,"stem":253,"icon":254},"Transactions","\u002Fen\u002Fdbx\u002Ftransactions","en\u002F07.dbx\u002F4.transactions","i-lucide-git-merge",{"title":256,"path":257,"stem":258,"icon":79},"Seeders","\u002Fen\u002Fdbx\u002Fseed","en\u002F07.dbx\u002F5.seed",{"title":260,"icon":192,"path":261,"stem":262,"children":263,"page":44},"envconf","\u002Fen\u002Fenvconf","en\u002F08.envconf",[264,267],{"title":52,"path":265,"stem":266,"icon":192},"\u002Fen\u002Fenvconf\u002Foverview","en\u002F08.envconf\u002F1.overview",{"title":268,"path":269,"stem":270,"icon":192},"Recipes","\u002Fen\u002Fenvconf\u002Frecipes","en\u002F08.envconf\u002F2.recipes",{"title":272,"icon":188,"path":273,"stem":274,"children":275,"page":44},"errs","\u002Fen\u002Ferrs","en\u002F09.errs",[276,279,283],{"title":52,"path":277,"stem":278,"icon":188},"\u002Fen\u002Ferrs\u002Foverview","en\u002F09.errs\u002F1.overview",{"title":280,"path":281,"stem":282,"icon":188},"API","\u002Fen\u002Ferrs\u002Fapi","en\u002F09.errs\u002F2.api",{"title":284,"path":285,"stem":286,"icon":188},"Integration","\u002Fen\u002Ferrs\u002Fintegration","en\u002F09.errs\u002F3.integration",{"title":288,"icon":289,"path":290,"stem":291,"children":292,"page":44},"events","i-lucide-workflow","\u002Fen\u002Fevents","en\u002F10.events",[293,297,302],{"title":294,"path":295,"stem":296,"icon":146},"Events","\u002Fen\u002Fevents\u002Foverview","en\u002F10.events\u002F1.overview",{"title":298,"path":299,"stem":300,"icon":301},"Outbox","\u002Fen\u002Fevents\u002Foutbox","en\u002F10.events\u002F2.outbox","i-lucide-inbox",{"title":303,"path":304,"stem":305,"icon":306},"Scheduling","\u002Fen\u002Fevents\u002Fscheduler","en\u002F10.events\u002F3.scheduler","i-lucide-calendar-clock",{"title":308,"icon":309,"path":310,"stem":311,"children":312,"page":44},"httperr","i-lucide-globe","\u002Fen\u002Fhttperr","en\u002F11.httperr",[313,316,321],{"title":52,"path":314,"stem":315,"icon":309},"\u002Fen\u002Fhttperr\u002Foverview","en\u002F11.httperr\u002F1.overview",{"title":317,"path":318,"stem":319,"icon":320},"Error responses","\u002Fen\u002Fhttperr\u002Ferror-responses","en\u002F11.httperr\u002F2.error-responses","i-lucide-octagon-alert",{"title":322,"path":323,"stem":324,"icon":325},"Validation","\u002Fen\u002Fhttperr\u002Fvalidation","en\u002F11.httperr\u002F3.validation","i-lucide-badge-check",{"title":327,"icon":328,"path":329,"stem":330,"children":331,"page":44},"logx","i-lucide-scroll-text","\u002Fen\u002Flogx","en\u002F12.logx",[332,335],{"title":52,"path":333,"stem":334,"icon":328},"\u002Fen\u002Flogx\u002Foverview","en\u002F12.logx\u002F1.overview",{"title":336,"path":337,"stem":338,"icon":47},"Monolog formatter","\u002Fen\u002Flogx\u002Fmonolog","en\u002F12.logx\u002F2.monolog",{"title":340,"icon":341,"path":342,"stem":343,"children":344,"page":44},"mail","i-lucide-mail","\u002Fen\u002Fmail","en\u002F13.mail",[345,348,352],{"title":52,"path":346,"stem":347,"icon":341},"\u002Fen\u002Fmail\u002Foverview","en\u002F13.mail\u002F1.overview",{"title":349,"path":350,"stem":351,"icon":341},"SMTP","\u002Fen\u002Fmail\u002Fsmtp","en\u002F13.mail\u002F2.smtp",{"title":353,"path":354,"stem":355,"icon":341},"MJML","\u002Fen\u002Fmail\u002Fmjml","en\u002F13.mail\u002F3.mjml",{"title":357,"icon":358,"path":359,"stem":360,"children":361,"page":44},"notify","i-lucide-bell","\u002Fen\u002Fnotify","en\u002F14.notify",[362,365,369],{"title":52,"path":363,"stem":364,"icon":358},"\u002Fen\u002Fnotify\u002Foverview","en\u002F14.notify\u002F1.overview",{"title":366,"path":367,"stem":368,"icon":358},"Database channel","\u002Fen\u002Fnotify\u002Fdatabase","en\u002F14.notify\u002F2.database",{"title":370,"path":371,"stem":372,"icon":358},"Broadcast channel","\u002Fen\u002Fnotify\u002Fbroadcast","en\u002F14.notify\u002F3.broadcast",{"title":374,"icon":375,"path":376,"stem":377,"children":378,"page":44},"paginate","i-lucide-list-ordered","\u002Fen\u002Fpaginate","en\u002F15.paginate",[379,382],{"title":52,"path":380,"stem":381,"icon":375},"\u002Fen\u002Fpaginate\u002Foverview","en\u002F15.paginate\u002F1.overview",{"title":383,"path":384,"stem":385,"icon":39},"Cursor pagination","\u002Fen\u002Fpaginate\u002Fcursor","en\u002F15.paginate\u002F2.cursor",{"title":387,"icon":183,"path":388,"stem":389,"children":390,"page":44},"queue","\u002Fen\u002Fqueue","en\u002F16.queue",[391,394],{"title":52,"path":392,"stem":393,"icon":375},"\u002Fen\u002Fqueue\u002Foverview","en\u002F16.queue\u002F1.overview",{"title":395,"path":396,"stem":397,"icon":183},"Tasks","\u002Fen\u002Fqueue\u002Ftasks","en\u002F16.queue\u002F2.tasks",{"title":399,"icon":400,"path":401,"stem":402,"children":403,"page":44},"storage","i-lucide-hard-drive","\u002Fen\u002Fstorage","en\u002F17.storage",[404,407,411,415,420],{"title":52,"path":405,"stem":406,"icon":400},"\u002Fen\u002Fstorage\u002Foverview","en\u002F17.storage\u002F1.overview",{"title":408,"path":409,"stem":410,"icon":400},"Disk API","\u002Fen\u002Fstorage\u002Fdisk-api","en\u002F17.storage\u002F2.disk-api",{"title":412,"path":413,"stem":414,"icon":400},"Memory and local disk","\u002Fen\u002Fstorage\u002Flocal","en\u002F17.storage\u002F3.local",{"title":416,"path":417,"stem":418,"icon":419},"S3","\u002Fen\u002Fstorage\u002Fs3","en\u002F17.storage\u002F4.s3","i-lucide-cloud",{"title":421,"path":422,"stem":423,"icon":424},"Testing","\u002Fen\u002Fstorage\u002Ftesting","en\u002F17.storage\u002F5.testing","i-lucide-flask-conical",{"title":426,"icon":427,"path":428,"stem":429,"children":430,"page":44},"telemetry","i-lucide-activity","\u002Fen\u002Ftelemetry","en\u002F18.telemetry",[431,434,438,443],{"title":52,"path":432,"stem":433,"icon":427},"\u002Fen\u002Ftelemetry\u002Foverview","en\u002F18.telemetry\u002F1.overview",{"title":435,"path":436,"stem":437,"icon":328},"Logging","\u002Fen\u002Ftelemetry\u002Flogging","en\u002F18.telemetry\u002F2.logging",{"title":439,"path":440,"stem":441,"icon":442},"OpenTelemetry","\u002Fen\u002Ftelemetry\u002Fopentelemetry","en\u002F18.telemetry\u002F3.opentelemetry","i-lucide-radar",{"title":444,"path":445,"stem":446,"icon":447},"Sentry","\u002Fen\u002Ftelemetry\u002Fsentry","en\u002F18.telemetry\u002F4.sentry","i-lucide-bug",{"id":449,"title":408,"body":450,"description":1539,"extension":1540,"links":1541,"meta":1542,"navigation":1543,"path":409,"seo":1544,"stem":410,"__hash__":1545},"docs_en\u002Fen\u002F17.storage\u002F2.disk-api.md",{"type":451,"value":452,"toc":1531},"minimark",[453,485,490,619,651,655,885,923,927,989,1008,1015,1124,1143,1147,1250,1278,1282,1471,1493,1497,1527],[454,455,456,460,461,468,469,472,473,476,477,480,481,484],"p",{},[457,458,459],"code",{},"Disk"," (from ",[462,463,465],"a",{"href":464},"\u002Fen\u002Fstorage\u002Foverview#disk-the-api-you-actually-call",[457,466,467],{},"storage.NewDisk",") is the type service code depends on; nothing outside ",[457,470,471],{},"main.go"," needs to know which ",[457,474,475],{},"Driver"," sits behind it. Every method takes a ",[457,478,479],{},"context.Context"," and a slash-separated ",[457,482,483],{},"path",", and every call is a traced OTel span, so a slow upload shows up in the trace waterfall right next to the DB queries it's near.",[486,487,489],"h2",{"id":488},"writes","Writes",[491,492,497],"pre",{"className":493,"code":494,"language":495,"meta":496,"style":496},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","err := disk.Put(ctx, \"avatars\u002F42.png\", r, storage.PutOptions{ContentType: \"image\u002Fpng\"})\nerr := disk.PutBytes(ctx, \"reports\u002F2026-07.csv\", data, storage.PutOptions{})\n","go","",[457,498,499,576],{"__ignoreMap":496},[500,501,504,508,512,515,518,522,525,528,531,534,538,541,543,546,548,552,554,557,560,563,566,568,571,573],"span",{"class":502,"line":503},"line",1,[500,505,507],{"class":506},"sTEyZ","err ",[500,509,511],{"class":510},"sMK4o",":=",[500,513,514],{"class":506}," disk",[500,516,517],{"class":510},".",[500,519,521],{"class":520},"s2Zo4","Put",[500,523,524],{"class":510},"(",[500,526,527],{"class":506},"ctx",[500,529,530],{"class":510},",",[500,532,533],{"class":510}," \"",[500,535,537],{"class":536},"sfazB","avatars\u002F42.png",[500,539,540],{"class":510},"\"",[500,542,530],{"class":510},[500,544,545],{"class":506}," r",[500,547,530],{"class":510},[500,549,551],{"class":550},"sBMFI"," storage",[500,553,517],{"class":510},[500,555,556],{"class":550},"PutOptions",[500,558,559],{"class":510},"{",[500,561,562],{"class":506},"ContentType",[500,564,565],{"class":510},":",[500,567,533],{"class":510},[500,569,570],{"class":536},"image\u002Fpng",[500,572,540],{"class":510},[500,574,575],{"class":510},"})\n",[500,577,579,581,583,585,587,590,592,594,596,598,601,603,605,608,610,612,614,616],{"class":502,"line":578},2,[500,580,507],{"class":506},[500,582,511],{"class":510},[500,584,514],{"class":506},[500,586,517],{"class":510},[500,588,589],{"class":520},"PutBytes",[500,591,524],{"class":510},[500,593,527],{"class":506},[500,595,530],{"class":510},[500,597,533],{"class":510},[500,599,600],{"class":536},"reports\u002F2026-07.csv",[500,602,540],{"class":510},[500,604,530],{"class":510},[500,606,607],{"class":506}," data",[500,609,530],{"class":510},[500,611,551],{"class":550},[500,613,517],{"class":510},[500,615,556],{"class":550},[500,617,618],{"class":510},"{})\n",[454,620,621,623,624,627,628,630,631,634,635,638,639,641,642,644,645,650],{},[457,622,521],{}," streams from an ",[457,625,626],{},"io.Reader",", so a large upload never sits fully in memory. ",[457,629,589],{}," is the convenience form for data you already hold as a ",[457,632,633],{},"[]byte"," (a generated report, a small in-memory buffer): it wraps a ",[457,636,637],{},"bytes.Reader"," and calls ",[457,640,521],{},". ",[457,643,556],{}," carries the metadata a driver may act on (content type, and whatever else a specific driver's options support); a driver that doesn't preserve some of it is a valid, if less capable, implementation, and ",[462,646,647],{"href":422},[457,648,649],{},"storagetest"," lets you assert whether it does.",[486,652,654],{"id":653},"reads","Reads",[491,656,658],{"className":493,"code":657,"language":495,"meta":496,"style":496},"b, err := disk.Get(ctx, \"avatars\u002F42.png\")            \u002F\u002F whole object, into memory\nrc, err := disk.Reader(ctx, \"avatars\u002F42.png\")        \u002F\u002F streamed; caller must Close()\nrc, err := disk.RangeReader(ctx, \"video.mp4\", 0, 1\u003C\u003C20) \u002F\u002F first MiB only\n\ninfo, err := disk.Stat(ctx, \"avatars\u002F42.png\")\nok := disk.Exists(ctx, \"avatars\u002F42.png\")\nmissing := disk.Missing(ctx, \"avatars\u002F42.png\")\n",[457,659,660,698,733,786,793,827,856],{"__ignoreMap":496},[500,661,662,665,667,670,672,674,676,679,681,683,685,687,689,691,694],{"class":502,"line":503},[500,663,664],{"class":506},"b",[500,666,530],{"class":510},[500,668,669],{"class":506}," err ",[500,671,511],{"class":510},[500,673,514],{"class":506},[500,675,517],{"class":510},[500,677,678],{"class":520},"Get",[500,680,524],{"class":510},[500,682,527],{"class":506},[500,684,530],{"class":510},[500,686,533],{"class":510},[500,688,537],{"class":536},[500,690,540],{"class":510},[500,692,693],{"class":510},")",[500,695,697],{"class":696},"sHwdD","            \u002F\u002F whole object, into memory\n",[500,699,700,703,705,707,709,711,713,716,718,720,722,724,726,728,730],{"class":502,"line":578},[500,701,702],{"class":506},"rc",[500,704,530],{"class":510},[500,706,669],{"class":506},[500,708,511],{"class":510},[500,710,514],{"class":506},[500,712,517],{"class":510},[500,714,715],{"class":520},"Reader",[500,717,524],{"class":510},[500,719,527],{"class":506},[500,721,530],{"class":510},[500,723,533],{"class":510},[500,725,537],{"class":536},[500,727,540],{"class":510},[500,729,693],{"class":510},[500,731,732],{"class":696},"        \u002F\u002F streamed; caller must Close()\n",[500,734,736,738,740,742,744,746,748,751,753,755,757,759,762,764,766,770,772,775,778,781,783],{"class":502,"line":735},3,[500,737,702],{"class":506},[500,739,530],{"class":510},[500,741,669],{"class":506},[500,743,511],{"class":510},[500,745,514],{"class":506},[500,747,517],{"class":510},[500,749,750],{"class":520},"RangeReader",[500,752,524],{"class":510},[500,754,527],{"class":506},[500,756,530],{"class":510},[500,758,533],{"class":510},[500,760,761],{"class":536},"video.mp4",[500,763,540],{"class":510},[500,765,530],{"class":510},[500,767,769],{"class":768},"sbssI"," 0",[500,771,530],{"class":510},[500,773,774],{"class":768}," 1",[500,776,777],{"class":510},"\u003C\u003C",[500,779,780],{"class":768},"20",[500,782,693],{"class":510},[500,784,785],{"class":696}," \u002F\u002F first MiB only\n",[500,787,789],{"class":502,"line":788},4,[500,790,792],{"emptyLinePlaceholder":791},true,"\n",[500,794,796,799,801,803,805,807,809,812,814,816,818,820,822,824],{"class":502,"line":795},5,[500,797,798],{"class":506},"info",[500,800,530],{"class":510},[500,802,669],{"class":506},[500,804,511],{"class":510},[500,806,514],{"class":506},[500,808,517],{"class":510},[500,810,811],{"class":520},"Stat",[500,813,524],{"class":510},[500,815,527],{"class":506},[500,817,530],{"class":510},[500,819,533],{"class":510},[500,821,537],{"class":536},[500,823,540],{"class":510},[500,825,826],{"class":510},")\n",[500,828,830,833,835,837,839,842,844,846,848,850,852,854],{"class":502,"line":829},6,[500,831,832],{"class":506},"ok ",[500,834,511],{"class":510},[500,836,514],{"class":506},[500,838,517],{"class":510},[500,840,841],{"class":520},"Exists",[500,843,524],{"class":510},[500,845,527],{"class":506},[500,847,530],{"class":510},[500,849,533],{"class":510},[500,851,537],{"class":536},[500,853,540],{"class":510},[500,855,826],{"class":510},[500,857,859,862,864,866,868,871,873,875,877,879,881,883],{"class":502,"line":858},7,[500,860,861],{"class":506},"missing ",[500,863,511],{"class":510},[500,865,514],{"class":506},[500,867,517],{"class":510},[500,869,870],{"class":520},"Missing",[500,872,524],{"class":510},[500,874,527],{"class":506},[500,876,530],{"class":510},[500,878,533],{"class":510},[500,880,537],{"class":536},[500,882,540],{"class":510},[500,884,826],{"class":510},[454,886,887,889,890,892,893,895,896,899,900,903,904,906,907,910,911,913,914,916,917,919,920,922],{},[457,888,678],{}," is the convenience form for small objects: it reads the whole thing into memory and closes the reader for you. For anything large, ",[457,891,715],{}," streams instead, and the caller owns closing it. ",[457,894,750],{}," opens a byte range ",[457,897,898],{},"[offset, offset+length)",", for resumable downloads or serving HTTP ",[457,901,902],{},"Range"," requests without reading the whole object. ",[457,905,811],{}," returns a ",[457,908,909],{},"FileInfo"," (size, content type, last-modified time, and so on) without transferring the body: a HEAD-style check. ",[457,912,841],{},"\u002F",[457,915,870],{}," are boolean conveniences over the same call, for the common case where you only care whether the object is there, not its metadata; a genuine backend error from the underlying ",[457,918,811],{}," is treated as \"not confirmed to exist\" rather than panicking or propagating silently, so check ",[457,921,811],{}," directly if you need to distinguish \"missing\" from \"storage is unreachable.\"",[486,924,926],{"id":925},"listing","Listing",[491,928,930],{"className":493,"code":929,"language":495,"meta":496,"style":496},"page, err := disk.List(ctx, storage.ListOptions{Prefix: \"avatars\u002F\", After: cursor})\n",[457,931,932],{"__ignoreMap":496},[500,933,934,937,939,941,943,945,947,950,952,954,956,958,960,963,965,968,970,972,975,977,979,982,984,987],{"class":502,"line":503},[500,935,936],{"class":506},"page",[500,938,530],{"class":510},[500,940,669],{"class":506},[500,942,511],{"class":510},[500,944,514],{"class":506},[500,946,517],{"class":510},[500,948,949],{"class":520},"List",[500,951,524],{"class":510},[500,953,527],{"class":506},[500,955,530],{"class":510},[500,957,551],{"class":550},[500,959,517],{"class":510},[500,961,962],{"class":550},"ListOptions",[500,964,559],{"class":510},[500,966,967],{"class":506},"Prefix",[500,969,565],{"class":510},[500,971,533],{"class":510},[500,973,974],{"class":536},"avatars\u002F",[500,976,540],{"class":510},[500,978,530],{"class":510},[500,980,981],{"class":506}," After",[500,983,565],{"class":510},[500,985,986],{"class":506}," cursor",[500,988,575],{"class":510},[454,990,991,993,994,996,997,1000,1001,913,1004,1007],{},[457,992,949],{}," returns one page of ",[457,995,909],{}," under ",[457,998,999],{},"ListOptions.Prefix",", with ",[457,1002,1003],{},"ListOptions.After",[457,1005,1006],{},"ListPage.ContinuationToken"," carrying you to the next page: meant for reconciliation and GC sweeps, not request-serving code paths one object at a time.",[454,1009,1010,1011,1014],{},"For walking an entire prefix without hand-rolling the pagination loop, ",[457,1012,1013],{},"Files"," is a Go 1.23+ range-over-func iterator:",[491,1016,1018],{"className":493,"code":1017,"language":495,"meta":496,"style":496},"for info, err := range disk.Files(ctx, \"avatars\u002F\") {\n    if err != nil {\n        return err\n    }\n    fmt.Println(info.Path, info.Size)\n}\n",[457,1019,1020,1061,1076,1084,1089,1119],{"__ignoreMap":496},[500,1021,1022,1026,1029,1031,1033,1035,1038,1040,1042,1044,1046,1048,1050,1052,1054,1056,1058],{"class":502,"line":503},[500,1023,1025],{"class":1024},"s7zQu","for",[500,1027,1028],{"class":506}," info",[500,1030,530],{"class":510},[500,1032,669],{"class":506},[500,1034,511],{"class":510},[500,1036,1037],{"class":1024}," range",[500,1039,514],{"class":506},[500,1041,517],{"class":510},[500,1043,1013],{"class":520},[500,1045,524],{"class":510},[500,1047,527],{"class":506},[500,1049,530],{"class":510},[500,1051,533],{"class":510},[500,1053,974],{"class":536},[500,1055,540],{"class":510},[500,1057,693],{"class":510},[500,1059,1060],{"class":510}," {\n",[500,1062,1063,1066,1068,1071,1074],{"class":502,"line":578},[500,1064,1065],{"class":1024},"    if",[500,1067,669],{"class":506},[500,1069,1070],{"class":510},"!=",[500,1072,1073],{"class":510}," nil",[500,1075,1060],{"class":510},[500,1077,1078,1081],{"class":502,"line":735},[500,1079,1080],{"class":1024},"        return",[500,1082,1083],{"class":506}," err\n",[500,1085,1086],{"class":502,"line":788},[500,1087,1088],{"class":510},"    }\n",[500,1090,1091,1094,1096,1099,1101,1103,1105,1108,1110,1112,1114,1117],{"class":502,"line":795},[500,1092,1093],{"class":506},"    fmt",[500,1095,517],{"class":510},[500,1097,1098],{"class":520},"Println",[500,1100,524],{"class":510},[500,1102,798],{"class":506},[500,1104,517],{"class":510},[500,1106,1107],{"class":506},"Path",[500,1109,530],{"class":510},[500,1111,1028],{"class":506},[500,1113,517],{"class":510},[500,1115,1116],{"class":506},"Size",[500,1118,826],{"class":510},[500,1120,1121],{"class":502,"line":829},[500,1122,1123],{"class":510},"}\n",[454,1125,1126,1128,1129,1131,1132,1134,1135,1138,1139,1142],{},[457,1127,1013],{}," pages through ",[457,1130,949],{}," internally and yields one ",[457,1133,909],{}," at a time; breaking out of the loop early (a ",[457,1136,1137],{},"break",", a ",[457,1140,1141],{},"return",") simply stops fetching further pages.",[486,1144,1146],{"id":1145},"copy-delete-move","Copy, Delete, Move",[491,1148,1150],{"className":493,"code":1149,"language":495,"meta":496,"style":496},"err := disk.Copy(ctx, \"uploads\u002Fstaging\u002Fx.png\", \"avatars\u002F42.png\")\nerr := disk.Delete(ctx, \"uploads\u002Fstaging\u002Fx.png\")\nerr := disk.Move(ctx, \"uploads\u002Fstaging\u002Fx.png\", \"avatars\u002F42.png\")\n",[457,1151,1152,1188,1215],{"__ignoreMap":496},[500,1153,1154,1156,1158,1160,1162,1165,1167,1169,1171,1173,1176,1178,1180,1182,1184,1186],{"class":502,"line":503},[500,1155,507],{"class":506},[500,1157,511],{"class":510},[500,1159,514],{"class":506},[500,1161,517],{"class":510},[500,1163,1164],{"class":520},"Copy",[500,1166,524],{"class":510},[500,1168,527],{"class":506},[500,1170,530],{"class":510},[500,1172,533],{"class":510},[500,1174,1175],{"class":536},"uploads\u002Fstaging\u002Fx.png",[500,1177,540],{"class":510},[500,1179,530],{"class":510},[500,1181,533],{"class":510},[500,1183,537],{"class":536},[500,1185,540],{"class":510},[500,1187,826],{"class":510},[500,1189,1190,1192,1194,1196,1198,1201,1203,1205,1207,1209,1211,1213],{"class":502,"line":578},[500,1191,507],{"class":506},[500,1193,511],{"class":510},[500,1195,514],{"class":506},[500,1197,517],{"class":510},[500,1199,1200],{"class":520},"Delete",[500,1202,524],{"class":510},[500,1204,527],{"class":506},[500,1206,530],{"class":510},[500,1208,533],{"class":510},[500,1210,1175],{"class":536},[500,1212,540],{"class":510},[500,1214,826],{"class":510},[500,1216,1217,1219,1221,1223,1225,1228,1230,1232,1234,1236,1238,1240,1242,1244,1246,1248],{"class":502,"line":735},[500,1218,507],{"class":506},[500,1220,511],{"class":510},[500,1222,514],{"class":506},[500,1224,517],{"class":510},[500,1226,1227],{"class":520},"Move",[500,1229,524],{"class":510},[500,1231,527],{"class":506},[500,1233,530],{"class":510},[500,1235,533],{"class":510},[500,1237,1175],{"class":536},[500,1239,540],{"class":510},[500,1241,530],{"class":510},[500,1243,533],{"class":510},[500,1245,537],{"class":536},[500,1247,540],{"class":510},[500,1249,826],{"class":510},[454,1251,1252,1254,1255,1257,1258,1260,1261,1264,1265,1268,1269,1271,1272,1274,1275,1277],{},[457,1253,1164],{}," is a server-side copy where the driver supports one, without the bytes passing through your process. ",[457,1256,1200],{}," is idempotent: deleting a path that isn't there is not an error. ",[457,1259,1227],{}," uses the driver's native move when it implements the optional ",[457,1262,1263],{},"Mover"," interface (see ",[462,1266,52],{"href":1267},"\u002Fen\u002Fstorage\u002Foverview#driver-the-backend-contract","); otherwise ",[457,1270,459],{}," does ",[457,1273,1164],{}," followed by ",[457,1276,1200],{}," itself, so callers never need to know which case they're in.",[486,1279,1281],{"id":1280},"urls","URLs",[491,1283,1285],{"className":493,"code":1284,"language":495,"meta":496,"style":496},"url, err := disk.URL(ctx, \"avatars\u002F42.png\")\nsigned, err := disk.TemporaryURL(ctx, \"exports\u002Forders.csv\", storage.TemporaryURLOptions{TTL: 15 * time.Minute})\nupload, err := disk.TemporaryUploadURL(ctx, \"uploads\u002F42.png\", storage.TemporaryUploadURLOptions{TTL: 5 * time.Minute})\n\nif disk.ProvidesTemporaryURLs() {\n    \u002F\u002F safe to offer direct-to-storage download\u002Fupload links\n}\n",[457,1286,1287,1319,1382,1441,1445,1462,1467],{"__ignoreMap":496},[500,1288,1289,1292,1294,1296,1298,1300,1302,1305,1307,1309,1311,1313,1315,1317],{"class":502,"line":503},[500,1290,1291],{"class":506},"url",[500,1293,530],{"class":510},[500,1295,669],{"class":506},[500,1297,511],{"class":510},[500,1299,514],{"class":506},[500,1301,517],{"class":510},[500,1303,1304],{"class":520},"URL",[500,1306,524],{"class":510},[500,1308,527],{"class":506},[500,1310,530],{"class":510},[500,1312,533],{"class":510},[500,1314,537],{"class":536},[500,1316,540],{"class":510},[500,1318,826],{"class":510},[500,1320,1321,1324,1326,1328,1330,1332,1334,1337,1339,1341,1343,1345,1348,1350,1352,1354,1356,1359,1361,1364,1366,1369,1372,1375,1377,1380],{"class":502,"line":578},[500,1322,1323],{"class":506},"signed",[500,1325,530],{"class":510},[500,1327,669],{"class":506},[500,1329,511],{"class":510},[500,1331,514],{"class":506},[500,1333,517],{"class":510},[500,1335,1336],{"class":520},"TemporaryURL",[500,1338,524],{"class":510},[500,1340,527],{"class":506},[500,1342,530],{"class":510},[500,1344,533],{"class":510},[500,1346,1347],{"class":536},"exports\u002Forders.csv",[500,1349,540],{"class":510},[500,1351,530],{"class":510},[500,1353,551],{"class":550},[500,1355,517],{"class":510},[500,1357,1358],{"class":550},"TemporaryURLOptions",[500,1360,559],{"class":510},[500,1362,1363],{"class":506},"TTL",[500,1365,565],{"class":510},[500,1367,1368],{"class":768}," 15",[500,1370,1371],{"class":510}," *",[500,1373,1374],{"class":506}," time",[500,1376,517],{"class":510},[500,1378,1379],{"class":506},"Minute",[500,1381,575],{"class":510},[500,1383,1384,1387,1389,1391,1393,1395,1397,1400,1402,1404,1406,1408,1411,1413,1415,1417,1419,1422,1424,1426,1428,1431,1433,1435,1437,1439],{"class":502,"line":735},[500,1385,1386],{"class":506},"upload",[500,1388,530],{"class":510},[500,1390,669],{"class":506},[500,1392,511],{"class":510},[500,1394,514],{"class":506},[500,1396,517],{"class":510},[500,1398,1399],{"class":520},"TemporaryUploadURL",[500,1401,524],{"class":510},[500,1403,527],{"class":506},[500,1405,530],{"class":510},[500,1407,533],{"class":510},[500,1409,1410],{"class":536},"uploads\u002F42.png",[500,1412,540],{"class":510},[500,1414,530],{"class":510},[500,1416,551],{"class":550},[500,1418,517],{"class":510},[500,1420,1421],{"class":550},"TemporaryUploadURLOptions",[500,1423,559],{"class":510},[500,1425,1363],{"class":506},[500,1427,565],{"class":510},[500,1429,1430],{"class":768}," 5",[500,1432,1371],{"class":510},[500,1434,1374],{"class":506},[500,1436,517],{"class":510},[500,1438,1379],{"class":506},[500,1440,575],{"class":510},[500,1442,1443],{"class":502,"line":788},[500,1444,792],{"emptyLinePlaceholder":791},[500,1446,1447,1450,1452,1454,1457,1460],{"class":502,"line":795},[500,1448,1449],{"class":1024},"if",[500,1451,514],{"class":506},[500,1453,517],{"class":510},[500,1455,1456],{"class":520},"ProvidesTemporaryURLs",[500,1458,1459],{"class":510},"()",[500,1461,1060],{"class":510},[500,1463,1464],{"class":502,"line":829},[500,1465,1466],{"class":696},"    \u002F\u002F safe to offer direct-to-storage download\u002Fupload links\n",[500,1468,1469],{"class":502,"line":858},[500,1470,1123],{"class":510},[454,1472,1473,1475,1476,1478,1479,1481,1482,1485,1486,1488,1489,1492],{},[457,1474,1304],{}," is for public content: a stable link, typically backed by a public bucket or a CDN base URL. ",[457,1477,1336],{}," hands out a time-limited, signed link for private content, so the client downloads straight from storage rather than proxying through your service. ",[457,1480,1399],{}," is the equivalent for direct client uploads, returning an ",[457,1483,1484],{},"UploadURL"," (the URL, and whatever headers or fields the caller needs to attach to the request, since that varies by driver). Not every driver can sign URLs; ",[457,1487,1456],{}," is a capability check you can use to branch instead of calling the method and handling ",[457,1490,1491],{},"ErrUnsupported"," after the fact.",[486,1494,1496],{"id":1495},"related-pages","Related pages",[1498,1499,1500,1506,1514,1519],"ul",{},[1501,1502,1503,1505],"li",{},[462,1504,52],{"href":405},": the Driver\u002FDisk\u002FManager model, decorators.",[1501,1507,1508,1510,1511,1513],{},[462,1509,412],{"href":413},": drivers to back a ",[457,1512,459],{}," with, for tests or a single-server deployment.",[1501,1515,1516,1518],{},[462,1517,416],{"href":417},": the S3-compatible driver, and its own presigned URL support.",[1501,1520,1521,1523,1524,1526],{},[462,1522,421],{"href":422},": the conformance suite that verifies a ",[457,1525,475],{}," behaves consistently.",[1528,1529,1530],"style",{},"html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}",{"title":496,"searchDepth":578,"depth":578,"links":1532},[1533,1534,1535,1536,1537,1538],{"id":488,"depth":578,"text":489},{"id":653,"depth":578,"text":654},{"id":925,"depth":578,"text":926},{"id":1145,"depth":578,"text":1146},{"id":1280,"depth":578,"text":1281},{"id":1495,"depth":578,"text":1496},"The Disk methods service code calls day to day: writes, reads, listing, URLs.","md",null,{},{"icon":400},{"title":408,"description":1539},"jDcZ11aGWTHB9T554cuSibuv9QfWUMiF04hqZCP-3A0",[1547,1549],{"title":52,"path":405,"stem":406,"description":1548,"icon":400,"children":-1},"Object storage behind a Driver\u002FDisk\u002FManager model, with in-memory, local-disk and S3-compatible drivers.",{"title":412,"path":413,"stem":414,"description":1550,"icon":400,"children":-1},"The two drivers that ship in the root storage module, for tests and single-server deployments.",1787346809309]