0

I'm trying to access a file on the server via an api that is behind Basic Auth. I then want to download that to a client's PC.

I've got the following code which does GET the url from behind the basic auth, however the image never downloads properly. I either get a failed network error message or I get a message saying I can't download it because my machine doesn't have an app installed to open it. It's a png so it definitely does!

It goes the whole way through the code and doesn't error so I'm confused as to why it's not downloading correctly to the clients machine (my pc while I'm testing!)

In the code I am specifying one file and I have specified it's length as bytes just to try and narrow down where I'm going wrong. Normally this could be any file that's being access of any length!

This is the code I have:

        //Create a stream for the file
        Stream stream = null;

        var size = fileResp.ContentLength; //I used this to determine the file was 64196 in size

        //This controls how many bytes to read at a time and send to the client
        int bytesToRead = 64196;

        // Buffer to read bytes in chunk size specified above
        byte[] buffer = new Byte[bytesToRead];


        string url= "https://myURL/images/image-2019-04-02-16-25-18-458.png";
        WebRequest myReq = WebRequest.Create(url);
        string credentials = "username:pwd";
        CredentialCache mycache = new CredentialCache();
        myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
        myReq.Method = "GET";

        // The number of bytes read
        try
        {
            //Create a response for this request
            HttpWebResponse fileResp = (HttpWebResponse)myReq.GetResponse();

            if (myReq.ContentLength > 0)
                fileResp.ContentLength = myReq.ContentLength;

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

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

            //Indicate the type of data being sent
            string contentType = MimeMapping.GetMimeMapping("new.png");
            resp.ContentType = contentType;
            string fileName = "new.png";
            //Name the file 
            resp.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
            
            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
        }
        finally
        {
            if (stream != null)
            {
                //Close the input stream
                stream.Close();
            }
        }

enter image description here

The output from here: fileResp.GetResponseStream();

enter image description here

hlh3406
  • 1,382
  • 5
  • 29
  • 46
  • 2
    Is this part of some kind of web server application (e.g. using ASP.NET)? If it is, it would be really useful to tag that. – ProgrammingLlama Jun 21 '21 at 08:49
  • 1
    Check the beginning of the file in notepad (or equivalent) to see what data look like. A image should have a ASCII header indicating the type of image. If you are seeing just ASCII characters than the file is probably GZIP and need to be uncompressed. – jdweng Jun 21 '21 at 09:12
  • If @jdweng's idea is correct, then see [this question](https://stackoverflow.com/questions/2815721/net-is-it-possible-to-get-httpwebrequest-to-automatically-decompress-gzipd-re) for a solution. – ProgrammingLlama Jun 21 '21 at 09:16

1 Answers1

0

At first, please try to test if the following code works on your computer.

private bool DownloadImage(string imgurl, string filename)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(imgurl);
    HttpWebResponse response = null;

    try
    {
        response = (HttpWebResponse)request.GetResponse();
    }
    catch
    {
        response = null;
        return false;
    }

    if (response != null && response.StatusCode == HttpStatusCode.OK)
    {
        Stream receiveStream = response.GetResponseStream();
        Bitmap bitmap = new Bitmap(receiveStream);

        if (bitmap != null)
        {
            bitmap.Save(filename);
        }

        receiveStream.Flush();
        receiveStream.Close();
        response.Close();
        return true;
    }
    else
    {
        return false;
    }
}

private void button1_Click(object sender, EventArgs e)
{
    string imgurl = "https://upload.wikimedia.org/wikipedia/commons/4/42/Cute-Ball-Go-icon.png";
    string filename = "D:\\download_test.png";
    bool bIsDownloadSuccess = DownloadImage(imgurl, filename);
}

This code works on me well. It doesn't have error, but returns false. Please check where false is returned. If it has some error, the problem will be on Windows System.

Please try and let me know. Thanks.

Ming Shou
  • 129
  • 7
  • I get true and this downloads fine to my PC – hlh3406 Jun 21 '21 at 10:01
  • It doesn't appear in my downloads on my browser window but instead saves straight to my D drive on my pc – hlh3406 Jun 21 '21 at 10:03
  • Yes, it is normal. It does not appear in your browser window because it is downloaded by the program. Isn't "downloading programmatically" what you want? – Ming Shou Jun 21 '21 at 10:56
  • No I'd like it to download via the browser so that the end user can see it - otherwise they'll click the button and if they aren't very good with IT, think that the file hasn't downloaded :( – hlh3406 Jun 21 '21 at 11:05
  • If you want for downloading to appear on browser window, c# programming will be needed. And, instead, we can show on c# interface that the file is downloading. – Ming Shou Jun 21 '21 at 12:13