<%@ Page Title="Basic Chunked Upload" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %>
<%@ Register Assembly="AjaxUploader" Namespace="AjaxUploader.Controls" TagPrefix="au" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Basic Chunked Upload - AjaxUploader v5.2 Demos</asp:Content>
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Basic Chunked Upload</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">Basic Chunked Upload</div> <div class="demo-card-body"> <p class="demo-description"> <strong>Chunked uploading splits large files into smaller pieces and sends them in parallel.</strong> Each chunk is independently retryable, so a flaky connection won't restart a 2&nbsp;GB upload from zero.
 Enable it with <code>EnableChunkedUpload="true"</code>.
 </p> <p class="demo-description" style="margin-top:0.5rem;"> <strong>Alternatives:</strong> for resumable uploads against an external tus server, see the
 <a href="../V5Features/StrategyTus.aspx">tus 1.0 demo</a>.
 For direct-to-cloud transfers that skip your server entirely, see
 <a href="../V5Features/StrategyS3.aspx">S3</a>,
 <a href="../V5Features/StrategyAzure.aspx">Azure Blob</a>, or
 <a href="../V5Features/StrategyGcs.aspx">Google Cloud Storage <span style="background:rgba(13,148,136,0.15);color:#0f766e;font-size:.55rem;font-weight:700;padding:.1rem .35rem;border-radius:999px;letter-spacing:.1em;">5.2</span></a>.
 Combine with <a href="../V5Features/IndexedDbResume.aspx">IndexedDB resume</a> for crash-survival.
 </p> <au:AjaxFileUpload ID="Uploader1" runat="server"
 EnableChunkedUpload="true"
 ChunkSize="1048576"
 AllowMultiple="true"
 ShowProgress="true" /> <h5 class="mt-4">How It Works</h5> <ol> <li>The file is split into chunks (default 1 MB each)</li> <li>Each chunk is sent as a separate HTTP request to the chunk URL</li> <li>The server reassembles chunks in order</li> <li>Progress is tracked across all chunks for a smooth experience</li> </ol> <h5>JavaScript API Equivalent</h5> <div id="jsChunkedUploader" style="margin-top:0.5rem;"></div> <div id="jsChunkedStatus" class="mt-2 small text-muted" aria-live="polite"></div> <div class="code-panel"> <pre><code>&lt;au:AjaxFileUpload ID="Uploader1" runat="server"
 EnableChunkedUpload="true"
 ChunkSize="1048576"
 AllowMultiple="true"
 ShowProgress="true" /&gt;

// JavaScript API approach
AjaxUploader.create(el, {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 chunkUrl: '<%= ResolveUrl("~/ajaxupload.axd/chunk") %>',
 chunked: true,
 chunkSize: 1048576,
 multiple: true,
 autoUpload: true
});</code></pre> </div> </div>
</div> 
</asp:Content> 
<asp:Content ID="ScriptsContent" ContentPlaceHolderID="ScriptsContent" runat="server">
<script> function clampPercent(value) {
 var pct = Number(value);
 if (!isFinite(pct)) return 0;
 return Math.max(0, Math.min(100, Math.round(pct)));
 }
 var jsChunkedHost = document.getElementById('jsChunkedUploader');
 var jsChunkedStatus = document.getElementById('jsChunkedStatus');
 if (window.AjaxUploader && typeof AjaxUploader.create === 'function' && jsChunkedHost) {
 AjaxUploader.create(jsChunkedHost, {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 chunkUrl: '<%= ResolveUrl("~/ajaxupload.axd/chunk") %>',
 chunked: true,
 chunkSize: 1048576,
 multiple: true,
 autoUpload: true,
 onTaskProgress: function (task, pct) {
 if (jsChunkedStatus) {
 jsChunkedStatus.textContent = task.fileName + ': ' + clampPercent(pct) + '%';
 }
 },
 onTaskComplete: function (task) {
 if (jsChunkedStatus) {
 jsChunkedStatus.textContent = task.fileName + ' upload complete';
 }
 }
 });
 }
</script>
</asp:Content>
