13

The following code is good for uploading text files, but it fails to upload JPEG files (not completely - the file name is good but the image is corrupted):

private void up(string sourceFile, string targetFile)
{
    try
    {
        string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
        string ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
        string ftpPassword = ConfigurationManager.AppSettings["ftpPass"];

        //string ftpURI = "";
        string filename = "ftp://" + ftpServerIP + "//" + targetFile;
        FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
        ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
        ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

        StreamReader stream = new StreamReader(sourceFile);
        Byte[] b = System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd());
        stream.Close();

        ftpReq.ContentLength = b.Length;
        Stream s = ftpReq.GetRequestStream();
        s.Write(b, 0, b.Length);
        s.Close();

        System.Net.FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();
        MessageBox.Show(ftpResp.StatusDescription);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

I have another solution that can upload a file:

private void Upload(string sourceFile, string targetFile)
{
    string ftpUserID;
    string ftpPassword;
    string ftpServerIP;
    ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
    ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
    ftpPassword = ConfigurationManager.AppSettings["ftpPass"];
    FileInfo fileInf = new FileInfo(sourceFile);
    FtpWebRequest reqFTP;

    // Create FtpWebRequest object from the Uri provided
    reqFTP = (FtpWebRequest)(FtpWebRequest.Create(new Uri("ftp://" + ftpServerIP + "//" + targetFile)));

    // Provide the WebPermission Credintials
    reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

    // Bypass default lan settings
    reqFTP.Proxy = null;

    // By default KeepAlive is true, where the control connection is not closed
    // after a command is executed.
    reqFTP.KeepAlive = false;

    // Specify the command to be executed.
    reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

    // Specify the data transfer type.
    reqFTP.UseBinary = true;

    // Notify the server about the size of the uploaded file
    reqFTP.ContentLength = fileInf.Length;

    // The buffer size is set to 2kb
    int buffLength = 2048;
    Byte[] buff;
    buff = new byte[buffLength];
    int contentLen;

    // Opens a file stream (System.IO.FileStream) to read the file to be uploaded
    FileStream fs = fileInf.OpenRead();

    try
    {
        // Stream to which the file to be upload is written
        Stream strm = reqFTP.GetRequestStream();

        // Read from the file stream 2kb at a time
        long filesize = fs.Length;
        int i=0;
        contentLen = fs.Read(buff, 0, buffLength);

        // Till Stream content ends
        while (contentLen != 0)
        {
            Application.DoEvents();
            // Write Content from the file stream to the FTP Upload Stream
            strm.Write(buff, 0, contentLen);
            contentLen = fs.Read(buff, 0, buffLength);
            i = i + 1;
            //Double percentComp = (i * buffLength) * 100 / filesize;
            //ProgressBar1.Value = (int)percentComp;
        }

        // Close the file stream and the Request Stream
        strm.Close();
        fs.Close();
    }

    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Upload Error");
    }
}

But here I have the opposite problem - the picture is good, but the file name is corrupted.

I know it is because of the encoding, but I don't know how to make the bytes array have the desired encoding...

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Asaf
  • 3,067
  • 11
  • 35
  • 54
  • I cannot understand, why would you have problem with corrupted file name with the second code, but not with the first code. And why would the accepted answer help with that. In all cases, you specify the file name the exactly same way. – Martin Prikryl Oct 25 '17 at 06:51
  • I'm sorry Martin. I wrote the question a decade ago. I dont remember what was the problem and what was the solution. I think you shoud open a new thread with your own question. – Asaf Oct 25 '17 at 07:01
  • I do not have a question, I just wonder what is the point of your question and the answer :) – Martin Prikryl Oct 25 '17 at 07:16
  • :) ... my past is hunting me ;)... I really dont remember. It's likely I did something wrong(bug) and its even possible that Microsoft had a bug that was fixed by now... – Asaf Oct 25 '17 at 07:23

6 Answers6

22

Try this bit:

private static void up(string sourceFile, string targetFile)
{            
    try
    {
        string ftpServerIP = ConfigurationManager.AppSettings["ftpIP"];
        string ftpUserID = ConfigurationManager.AppSettings["ftpUser"];
        string ftpPassword = ConfigurationManager.AppSettings["ftpPass"];
        ////string ftpURI = "";
        string filename = "ftp://" + ftpServerIP + "//" + targetFile; 
        FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
        ftpReq.UseBinary = true;
        ftpReq.Method = WebRequestMethods.Ftp.UploadFile;
        ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

        byte[] b = File.ReadAllBytes(sourceFile);

        ftpReq.ContentLength = b.Length;
        using (Stream s = ftpReq.GetRequestStream())
        {
            s.Write(b, 0, b.Length);
        }

        FtpWebResponse ftpResp = (FtpWebResponse)ftpReq.GetResponse();

        if (ftpResp != null)
        {
            MessageBox.Show(ftpResp.StatusDescription);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}
Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87
2

You should be using a Stream to read binary files, not a StreamReader. StreamReader is designed to read text files only.

Mark
  • 11,257
  • 11
  • 61
  • 97
  • I tried toying with the code for 3 hours now, and I also found the streamReader that comes with encoding(in the constructor) - yet I could not understand how to use not the streamreader nor the stream objects. Streams are like a black box to me :( – Asaf Aug 26 '10 at 15:08
2

In your first code example, enable binary transfer: FtpWebRequest.UseBinary = true. Otherwise it will convert what it thinks are textual line endings between the various platform conventions (but are actually part of the image).

Paul Ruane
  • 37,459
  • 12
  • 63
  • 82
  • There must be something else missing... I added the line you game me - but nothing changed. – Asaf Aug 26 '10 at 15:20
  • Yes, see Mark's answer: you are attempting to read the file as UTF8 text. Ditch the **StreamReader** and read the bytes directly from the stream, e.g. with **Stream.Read()**. – Paul Ruane Aug 26 '10 at 22:16
2

Your second snippet does it the right way. It uses FileStream, not StreamReader. StreamReader is only suitable for text files.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
0

If you have this problem: The requested FTP command is not supported when using HTTP

you need set proxy in Null or Nothing.

ftpReq.Proxy = null;

You can see this blog.

http://mycodetrip.com/2008/10/29/fix-for-error-the-requested-ftp-command-is-not-supported-when-using-http-proxy_118/comment-page-1/#comment-2825

Thanks.

Erick Martinez
  • 283
  • 4
  • 7
0

System.Text.Encoding.UTF8.GetBytes(stream.ReadToEnd());

Don't do this unless your stream's contents are text. Change your function to accept a boolean parameter "binary", and use the latter, working method if that flag is set.

egrunin
  • 24,650
  • 8
  • 50
  • 93
Jonathan
  • 1,487
  • 11
  • 12