title: Download file and check integrity
body: <p>I have a server running PHP on which i can upload zip archives using a custom form in administration panel. When I upload a zip archive, I calculate a CRC32 checksum of it and I insert it into my database for future download integrity checks:</p>
  <pre><code>$zipchecksum = strtoupper(hash_file('crc32', $zippath));
  $mysqli-&gt;query(&quot;INSERT INTO files VALUES (NULL, '$zipname', '$zippath')&quot;);
  </code></pre>
  <p>When I query the server for an available file to download using my C# client, I also receive that checksum in the response and if a new file is available, I download it:</p>
  <pre><code>HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Properties.Settings.Default.URLDownload);
  request.Accept = &quot;application/octet-stream&quot;;
  request.ContentType = &quot;application/x-www-form-urlencoded&quot;;
  request.Method = WebRequestMethods.Http.Post;
  
  using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
  using (Stream responseStream = response.GetResponseStream())
  using (MemoryStream memoryStream = new MemoryStream())
  {
      responseStream.CopyTo(memoryStream);
  
      Crc32 crc = new Crc32();
      crc.Update(memoryStream.GetBuffer());
  
      if (crc.Value.ToString(&quot;X&quot;) != m_ServerData.CRC)
          throw new Exception(&quot;Malformed zip file received!&quot;);
  
      ZipFile file = new ZipFile(memoryStream);
      // ...
  }
  </code></pre>
  <p>And here is my response:</p>
  <pre><code>header('Cache-Control: must-revalidate, pre-check=0, post-check=0');
  header('Content-Description: File Transfer');
  header('Content-Disposition: attachment; filename=&quot;'.$zipname.'&quot;');
  header('Content-Length: '.filesize($filepath));
  header('Content-Transfer-Encoding: binary');
  header('Content-Type: application/octet-stream');
  header('Expires: 0');
  header('Pragma: public');
  
  readfile($zippath);
  </code></pre>
  <p>Now, here comes the integrity check. The CRC32 checksum calculated by PHP is completely different from the one I calculate in my client using the Crc32 class from ICSharpCode.SharpZipLib. For example:</p>
  <blockquote>
  <p>PHP Server -&gt; CF83A609</p>
  <p>C# Client -&gt; 3FB78619</p>
  </blockquote>
  <p>I also tried to use another PHP function:</p>
  <pre><code>$zipcontents = file_get_contents($zippath); 
  $crc = crc32($zipcontents);
  $zipchecksum = strtoupper(dechex(crc32($zipcontents)));
  $mysqli-&gt;query(&quot;INSERT INTO files VALUES (NULL, '$zipname', '$zippath')&quot;);
  </code></pre>
  <p>But the result is once again different.</p>
  <blockquote>
  <p>PHP Server -&gt; A6A642D0</p>
  <p>C# Client -&gt; 3FB78619</p>
  </blockquote>
  <p>So it seems like the buffer that PHP is using to calculate the checksum differs from the one the client receives from server. Well... anyone has a solution?</p>