<%@ Page Title="Web Worker file hashing" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" %> 
<asp:Content ID="TitleContent" ContentPlaceHolderID="TitleContent" runat="server">Web Worker hashing - AjaxUploader v5.2 Demos</asp:Content> 
<asp:Content ID="HeaderContent" ContentPlaceHolderID="HeaderTitle" runat="server">Web Worker hashing</asp:Content> 
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server"> 
<div class="demo-card"> <div class="demo-card-header">SHA-256 &amp; CRC32 off the main thread</div> <div class="demo-card-body"> <p class="demo-description"> Gigabyte hashing runs in an inline Web Worker so the UI stays responsive during the computation. CRC32 uses an 8x faster 256-entry table-driven algorithm; SHA-256 calls <code>crypto.subtle.digest</code> inside the worker. A CSP-safe main-thread fallback kicks in automatically when Workers or Blob URLs are blocked.
 </p> <div class="demo-expect"><strong>What you should see:</strong> SHA-256 computed in a Web Worker so hashing a big file does not freeze the tab - the hash shows per file before upload.</div> <div class="d-flex gap-2 mb-2 mt-4">
 <button type="button" class="btn btn-primary" id="startBtn_hashUploader">Start upload</button>
 <button type="button" class="btn btn-outline-secondary" id="clearBtn_hashUploader">Clear queue</button>
 </div>
 <div id="hashUploader"></div> <script> (function () {
 function init() {
 if (!window.AjaxUploader || typeof AjaxUploader.create !== 'function') return; // graceful no-op if runtime missing
 var uploader = AjaxUploader.create('#hashUploader', {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 autoUpload: false,
 multiple: true,
 computeHash: true,
 hashAlgorithm: 'sha256'
 });
 var startButton = document.getElementById('startBtn_hashUploader');
 var clearButton = document.getElementById('clearBtn_hashUploader');
 if (startButton) {
 startButton.addEventListener('click', function () {
 if (uploader && typeof uploader.upload === 'function') uploader.upload();
 });
 }
 if (clearButton) {
 clearButton.addEventListener('click', function () {
 if (uploader && typeof uploader.clear === 'function') uploader.clear();
 });
 }
 }
 if (document.readyState !== 'loading') init();
 else document.addEventListener('DOMContentLoaded', init);
 })();
 </script> <div class="alert alert-info mt-3" role="alert"> <strong>Try it:</strong> pick a large file. While it hashes, scroll or interact with the page - the UI never freezes. The computed hash lands on <code>task.hash</code> and is sent to the server with the upload.
 </div> <h5 class="mt-4">Configuration</h5> <div class="code-panel"> 
<pre><code>AjaxUploader.create('#uploader', {
 uploadUrl: '<%= ResolveUrl("~/ajaxupload.axd/upload") %>',
 computeHash: true,
 hashAlgorithm: 'sha256' <span style="color:#94a3b8">// or 'crc32'</span> 
});</code></pre> </div> <h5 class="mt-4">Use cases</h5> <ul class="mb-3"> <li><strong>Content-addressable storage:</strong> use the hash as the storage key so identical uploads de-dupe.</li> <li><strong>Integrity verification:</strong> re-hash on the server and compare to catch corruption.</li> <li><strong>Duplicate detection:</strong> reject files already in the queue by hash, not by name.</li> <li><strong>Signature workflows:</strong> sign the hash rather than the bytes for document signing flows.</li> </ul> <h5 class="mt-4">Fallback behaviour</h5> <p>When Workers or Blob URLs are unavailable (strict CSP, older browsers), hashing transparently runs on the main thread. The API and the resulting <code>task.hash</code> value are identical; only UI responsiveness during the hash differs.</p> </div> 
</div> 
</asp:Content> 
