<%@ Page Title="Chunk Retry" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %>
<%@ Register Assembly="AjaxUploader" Namespace="AjaxUploader.Controls" TagPrefix="au" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Chunk Retry - AjaxUploader v5.2 Demos</asp:Content>
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Chunk Retry</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">Automatic Retry on Chunk Failure</div> <div class="demo-card-body"> <p class="demo-description"> When a chunk fails to upload due to a network error, AjaxUploader automatically retries
 the failed chunk. Configure the number of retry attempts and delay between retries.
 </p> <div class="demo-expect"><strong>What you should see:</strong> 1&nbsp;MB chunks with up to 3 retries, 2&nbsp;s apart (adjustable with the selector). Kill your network mid-upload and only the failed chunk is resent - the log shows each retry.</div> <au:AjaxFileUpload ID="Uploader1" runat="server"
 EnableChunkedUpload="true"
 ChunkSize="1048576"
 MaxRetries="3"
 RetryDelay="2000" /> <div class="mb-3 mt-3"> <label class="form-label fw-bold" for="retryCount">Max Retries</label> <select id="retryCount" class="form-select" style="width:auto;display:inline-block;"> <option value="0">0 (No retry)</option> <option value="1">1</option> <option value="3" selected>3</option> <option value="5">5</option> </select> </div> <div id="log" class="mt-3 p-2 bg-light border rounded" role="log" aria-live="polite" style="max-height:160px;overflow-y:auto;font-size:.85rem;"></div> <div class="code-panel"> <pre><code>&lt;au:AjaxFileUpload ID="Uploader1" runat="server"
 EnableChunkedUpload="true"
 ChunkSize="1048576"
 MaxRetries="3"
 RetryDelay="2000" /&gt;

// JavaScript API approach
AjaxUploader.create('#uploader', {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 chunkUrl: '<%= ResolveUrl("~/ajaxupload.axd/chunk") %>',
 chunkCompleteUrl: '<%= ResolveUrl("~/ajaxupload.axd/chunk/complete") %>',
 chunked: true,
 chunkSize: 1 * 1024 * 1024,
 retries: 3, // retry failed chunks up to 3 times
 onTaskProgress: function(task) {
 log('Chunk progress: ' + clampPercent(task.percent) + '%');
 },
 onTaskError: function(task, error) {
 log('Failed after retries: ' + error);
 }
});</code></pre> </div> </div>
</div> 
</asp:Content> 
<asp:Content ID="ScriptsContent" ContentPlaceHolderID="ScriptsContent" runat="server">
<script> var logEl = document.getElementById('log');
 var retryCount = document.getElementById('retryCount');
 function clampPercent(value) {
 var pct = Number(value);
 if (!isFinite(pct)) return 0;
 return Math.max(0, Math.min(100, Math.round(pct)));
 }
 function log(msg) {
 if (!logEl) return;
 var div = document.createElement('div');
 div.textContent = '[' + new Date().toLocaleTimeString() + '] ' + msg;
 logEl.appendChild(div);
 logEl.scrollTop = logEl.scrollHeight;
 }

 var uploader = window.AjaxUploader && AjaxUploader.getInstance ? AjaxUploader.getInstance('Uploader1') : null;
 if (uploader) {
 uploader.on('taskStart', function(task) {
 log('Started: ' + task.fileName);
 });
 uploader.on('taskProgress', function(task) {
 log('Progress: ' + task.fileName + ' ' + clampPercent(task.percent) + '%');
 });
 uploader.on('taskError', function(task, error) {
 log('Error: ' + task.fileName + ' - ' + error);
 });
 uploader.on('taskComplete', function(task) {
 log('Completed: ' + task.fileName);
 });
 } else {
 log('Uploader API is still loading. Refresh the page or try again in a moment.');
 }

 if (retryCount) retryCount.addEventListener('change', function() {
 if (uploader) {
 uploader.setOptions({ retries: parseInt(this.value) });
 log('Retries set to ' + this.value);
 }
 });
</script>
</asp:Content>
