Search code examples
c#iishttpwebrequestxlsxcorrupt

downloaded xlsx file corrupt useing IIS and c# httpwebrequest


I have the following problem: When I'm downloading xlsx or docx file, the downloaded file is corrupt. Other types of files (Pdf for example) is working fine. I have also tested different MIME-Types (application/vnd.ms-excel or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet or application/octet-stream). Following Code is in use:

protected void btnActionDocAnsehen_Click(object sender, CommandEventArgs e)
{
    string connectionString = ConfigurationManager.ConnectionStrings["dataConnection"].ToString();
    SqlConnection conn = new SqlConnection(connectionString);

    conn.Open();

    //New Code for Downloading file
    string filepath = pfad;
    #endregion

    #region [Datenabruf mit WebDAV]
    //Create a stream for the file
    Stream stream = null;
    //This controls how many bytes to read at a time and send to the client
    int bytesToRead = 10000;
    // Buffer to read bytes in chunk size specified above
    byte[] buffer = new Byte[bytesToRead];

    try
    {
        // --------------- COPY REQUEST --------------- //

        // Create an HTTP request for the URL.
        HttpWebRequest httpCopyRequest =
          (HttpWebRequest)WebRequest.Create(filepath);

        httpCopyRequest.Timeout = 3000;

        // Pre-authenticate the request.
        httpCopyRequest.PreAuthenticate = true;


        //Create a response for this request
        HttpWebResponse httpCopyResponse = (HttpWebResponse)httpCopyRequest.GetResponse();


        if (httpCopyRequest.ContentLength > 0)
            httpCopyResponse.ContentLength = httpCopyRequest.ContentLength;

        //Get the Stream returned from the response
        stream = httpCopyResponse.GetResponseStream();

        // prepare the response to the client. resp is the client Response
        var resp = HttpContext.Current.Response;

        //Indicate the type of data being sent
        resp.ContentType = ReturnFiletype(Path.GetExtension(filepath));

        //Name the file 
        resp.AddHeader("Content-Disposition", "attachment; filename=\"" + pfad + "\"");

        int length;
        do
        {
            // Verify that the client is connected.
            if (resp.IsClientConnected)
            {
                // Read data into the buffer.
                length = stream.Read(buffer, 0, bytesToRead);

                // and write it out to the response's output stream
                resp.OutputStream.Write(buffer, 0, length);

                // Flush the data
                resp.Flush();

                //Clear the buffer
                buffer = new Byte[bytesToRead];
            }
            else
            {
                // cancel the download if client has disconnected
                length = -1;
            }
        } while (length > 0); //Repeat until no data is read
    }
    catch (WebException ex)
    {
        string message = "Die Datei konnte auf dem Server nicht gefunden werden! Bitte kontaktieren Sie die Administration!";
        //string message = filepath;
        ClientScript.RegisterStartupScript(GetType(), "alert", "alert('" + message + "');", true);
    }
    finally
    {
        if (stream != null)
        {
            //Close the input stream
            stream.Close();
        }
    }
    #endregion
}

Solution

  • If you don't end your HttpContext.Current.Response it will add the page to the bottom of the (File) OutputStream.

    Check your file with text editor (notepad) and you will probably see something like this at the bottom:

    <!DOCTYPE html>
    
    <html lang="en">
    <head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>
    (...)
    

    I guess it works with pdf's because probably your PdfReader ignores anything that is not properly formatted, or after some tag.

    You simply have to add resp.End() after the loop, like

      (...)
    } while (length > 0); //Repeat until no data is read
    
    resp.End();