Share via


How To Download A File With A Special Character In Its Name

Question

Tuesday, September 5, 2017 2:59 PM

I am trying to retrieve a file located at http://10.10.10.10/CardsPro+.exebut it returns a 404 message as its unable to locate the file. It works when I change the file name to not include the special character
        
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;

namespace CardsPro_Updater
{
    internal partial class UpdateInfoDownloadForm : Form
    {
        private WebClient webClient;
        private BackgroundWorker bgWorker;
        private string tempFile;
        private string md5;
        internal string TempFilePath
        {
            get { return this.tempFile; }
        }
        internal UpdateInfoDownloadForm(Uri location, string md5, Icon programIcon)
        {
            InitializeComponent();
            if (programIcon != null)
            {
                this.Icon = programIcon;
            }
            tempFile = Path.GetTempFileName();
            this.md5 = md5;
            webClient = new WebClient();
            webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
            webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
            
            bgWorker = new BackgroundWorker();
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(BgWorker_RunWorkerCompleted);

            try
            {
               // string encLoc = Uri.EscapeUriString(location.ToString());
                //string nencLoc = Uri.EscapeDataString(location.ToString());
                string strend = location.ToString().Substring(location.ToString().LastIndexOf('/')+1);

                string strstart = location.ToString().Substring(0,location.ToString().LastIndexOf('/')+1);

                strend = System.Web.HttpUtility.UrlEncode(strend);
                
                Uri locn = new Uri(strstart+strend); //encLoc);//(

                webClient.DownloadFileAsync(locn, this.tempFile);


            }
            catch(Exception ex)
            { this.DialogResult = DialogResult.No; this.Close(); }
        }

        private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            try
            {
                this.progressBar.Value = e.ProgressPercentage;
                this.label1.Text = string.Format("Downloaded {0} of {1}", FormatBytes(e.BytesReceived, 1, true).ToString(), FormatBytes(e.TotalBytesToReceive, 1, true).ToString());
            }
            catch (Exception ex)
            {
                
            }
        }

        private string FormatBytes(long bytes, int decimalplaces, bool showByteType)
        {
            string txt=null;
            try
            {
                double newBytes = bytes;
                string formatString = "{0";
                string byteType = "B";

                if (newBytes > 1024 && newBytes < 1048576)
                {
                    newBytes /= 1024;
                    byteType = "KB";
                }
                else if (newBytes > 1048576 && newBytes < 1073741824)
                {
                    newBytes /= 1048576;
                    byteType = "MB";
                }
                else
                {
                    newBytes /= 1073741824;
                    byteType = "GB";
                }
                if (decimalplaces > 0)
                {
                    formatString += ":0.";
                }

                for (int i = 0; i < decimalplaces; i++)
                {
                    formatString += "0";
                }

                formatString += "}";

                if (showByteType)
                {
                    formatString += byteType;

                }

                txt= string.Format(formatString, newBytes);
            }
            catch (Exception ex)
            {
            }
            return txt;
        }

        private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                this.DialogResult = DialogResult.No;
                this.Close();
            }
            else if (e.Cancelled)
            {
                this.DialogResult = DialogResult.Abort;
                this.Close();
            }
            else
            {
                lblProgress.Text = "Verifying Download....";
                progressBar.Style = ProgressBarStyle.Marquee;
                bgWorker.RunWorkerAsync(new string[] { this.tempFile, this.md5 });
            }
        }

        private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string file = ((string[])e.Argument)[0];
            string updateMd5 = ((string[])e.Argument)[1];
            string md5value= Hasher.HashFile(file, HashType.MD5);
            if (md5value != updateMd5)
                e.Result = DialogResult.No;
            else
                e.Result = DialogResult.OK;
        }

        private void BgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.DialogResult = ( DialogResult)e.Result;
            this.Close();
        }

        private void closePanelButton_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void UpdateInfoDownloadForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (webClient.IsBusy)
            {
                webClient.CancelAsync();
                this.DialogResult = DialogResult.Abort;
            }

            if (bgWorker.IsBusy)
            {
                bgWorker.CancelAsync();
                this.DialogResult = DialogResult.Abort;
            }
        }
    }
}

All replies (13)

Wednesday, September 6, 2017 10:21 AM âś…Answered | 1 vote

Hello tks_tman,

For a file address contains special characters , you want to download the file depends on the deployment of server support  special character access .

For example , if IIS server don't support to access with special character, what changes have you made with url , the result is impossible.

The following is a solution about handling the filename contains special character , you could take reference with it.

https://helpx.adobe.com/experience-manager/kb/CannotOpenAFileHavingSpecialCharactersInTheFilenameOnIIS.html

Best regards,
feih_7

Note: This response contains a reference to a third-party World Wide Web site. Microsoft is providing this information as a convenience to you.
Microsoft does not control these sites and has not tested any software or information found on these sites; Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there.
There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

MSDN Community Support
Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact [email protected].


Tuesday, September 5, 2017 3:23 PM

Use System.Uri.EscapeUriString(string)

Here is the MSDN reference:

Uri.EscapeUriString Method (String)

From the snippet you posted , this would be a good place for it, or maybe under Path.GetTempFileName()

        internal string TempFilePath
        {
            get { return System.Uri.EscapeUriString(this.tempFile); }
        }

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 3:41 PM

It returns the string unchanged. 

string encLoc = Uri.EscapeUriString("http://10.10.10.10/CardsPro+.exe");

encLoc - holds the value "http://10.10.10.10/CardsPro+.exe"


Tuesday, September 5, 2017 3:47 PM

It returns the string unchanged. 

string encLoc = Uri.EscapeUriString("http://10.10.10.10/CardsPro+.exe");

encLoc - holds the value "http://10.10.10.10/CardsPro+.exe"

This is what you want:

CardsPro%2B.exe

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 3:49 PM

It returns the string unchanged. 

string encLoc = Uri.EscapeUriString("http://10.10.10.10/CardsPro+.exe");

encLoc - holds the value "http://10.10.10.10/CardsPro+.exe"

This is what you want:

CardsPro%2B.exe

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com

I tried to be generic, but looks like you will need a reference to System.Web

use HttpUtility.UrlEncode instead of the Uri encode I mentioned before.

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 4:20 PM

Still reports 404 with name"CardsPro+.exe" and works when the filename is changed to CardsPro.exe. Any other suggestions?


Tuesday, September 5, 2017 4:34 PM

Still reports 404 with name"CardsPro+.exe" and works when the filename is changed to CardsPro.exe. Any other suggestions?

Well, if you used the Encoder, it would give you the error with CardsPro%2B.exe, not CardsPro+.exe.

Can you post the entire C# class you have, using the UrlEncoder for our review?

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 5:00 PM

Just did


Tuesday, September 5, 2017 5:23 PM

Just did

Lets create another Uri instance with the encoded path and use that other Uri. Lets see what that does. Can you try?

           try
            {
                Uri locn = new Uri(System.Web.HttpUtility.UrlEncode(location.AbsolutePath));
                webClient.DownloadFileAsync(locn, this.tempFile);
            }
            catch(Exception ex)
            { this.DialogResult = DialogResult.No; this.Close(); }
        }

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 7:07 PM

location.AbsolutePath has the value : "/CardsPro+.exe""

Which causes an exception ""Invalid URI: The format of the URI could not be determined.""


Tuesday, September 5, 2017 8:35 PM

location.AbsolutePath has the value : "/CardsPro+.exe""

Which causes an exception ""Invalid URI: The format of the URI could not be determined.""

Great, we found our culprit!

Your calling component needs to pass the absolute path (See this: Uri.AbsolutePath Property ). 

Examples of valid URI absolute paths are here: Absolute URIs

Is it in your reach to have the calling component pass an absolute path? 

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Tuesday, September 5, 2017 9:04 PM

Let me clarify:

Letme clarify

location.AbsolutePath has the value : "/CardsPro+.exe""

Which causes an exception ""Invalid URI: The format of the URI could not be determined.""

The above happens after making the changes you suggested.. "Lets create another Uri instance with the encoded path and use that other Uri. Lets see what that does. Can you try?"

location already has the absolute path.

The problem is that Uri cannot be constructed after the string parameter is escaped and changed to "http%3A%2F%2F10.10.1.211%3A8600%2FCardsPro%2B.exe" or 

"http://10.10.1.211:8600/CardsPro+.exe" 

if I do the following to construct the Uri

                string strend = location.ToString().Substring(location.ToString().LastIndexOf('/')+1); 

                string strstart = location.ToString().Substring(0,location.ToString().LastIndexOf('/')+1); strstart = "http://10.10.1.211:8600/"

This location cannot be found and I get a 404

                 

                strend = System.Web.HttpUtility.UrlEncode(location.AbsolutePath.Substring(1, location.AbsolutePath.Length-1)); // strend = "CardsPro%2b.exe"
                string strying = strstart + strend;
                Uri locn = new Uri(strstart+strend); //locn={http://10.10.1.211:8600/CardsPro%2b.exe}

In the above snippet this location cannot be found with : webClient.DownloadFileAsync(locn, this.tempFile); and another 404 is given

In the option you provided :

try
            {
                Uri locn = new Uri(System.Web.HttpUtility.UrlEncode(location.AbsolutePath));
                webClient.DownloadFileAsync(locn, this.tempFile);
            }
            catch(Exception ex)
            { this.DialogResult = DialogResult.No; this.Close(); } 

locn fails to be constructed as the location.AbsolutePath= "/CardsPro+.exe" which cannot be used to construct a Uri.


Wednesday, September 6, 2017 2:18 PM

Thank you guys!