nespa
asked on
FtpWebRequest help
Any success w/ FtpWebRequest in 2.0? I've been working w/ a few examples & can't seem to get any to work. A step in the right direction would be a huge help.
I don't need anything complex (i.e., I can make it asynchronous request later on)... some simple code & a URI example would be most helpful.
Thanks.
I don't need anything complex (i.e., I can make it asynchronous request later on)... some simple code & a URI example would be most helpful.
Thanks.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Forgot to close this question out -- what worked for me was a post w/ some code I modified. Here's the code that worked... and I think most of my problems might have been due to incorrect testing data... stuff like forgetting to escape the backslash while testing; simple stupid stuff. Anyway, here's what worked:
public string UploadFile(string ftpHost, string targetFolderOnHost, string filename, string ftpUsername, string ftpPword, bool returnUniqueNewFilename)
{
System.Collections.ArrayLi st errors = new System.Collections.ArrayLi st();
string requestMethod = "";
string uploadPath = "";
// set up the host string to request. this includes the target folder and the target file name (based on the source filename)
if (returnUniqueNewFilename)
{
requestMethod = System.Net.WebRequestMetho ds.Ftp.UploadFileWithUniqueName;
uploadPath = String.Format("{0}/{1}{2}" , ftpHost, targetFolderOnHost == "" ? "" : targetFolderOnHost + "/", "");
}
else
{
requestMethod = System.Net.WebRequestMetho ds.Ftp.UploadFile;
uploadPath = String.Format("{0}/{1}{2}" , ftpHost, targetFolderOnHost == "" ? "" : targetFolderOnHost + "/", Path.GetFileName(filename) );
}
if (!uploadPath.ToLower().Sta rtsWith("ftp://" ))
{
uploadPath = "ftp://" + uploadPath;
}
System.Net.FtpWebRequest request = (System.Net.FtpWebRequest) System.Net .WebReques t.Create(u ploadPath) ;
request.UseBinary = true;
request.UsePassive = true;
request.Method = requestMethod;
request.Credentials = new System.Net.NetworkCredenti al(ftpUser name, ftpPword);
// Copy the contents of the file to the request stream.
long FileSize = new System.IO.FileInfo(filenam e).Length;
string FileSizeDescription = GetFileSize(FileSize); // e.g. "2.4 Gb" instead of 240000000000000 bytes etc...
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize]; // this buffer stores each chunk, for sending to the web service via MTOM
using (System.IO.Stream requestStream = request.GetRequestStream() )
{
using (System.IO.FileStream fs = System.IO.File.Open(filena me, System.IO.FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
// send the chunks to the web service one by one, until FileStream.Read() returns 0, meaning the entire file has been read.
while (BytesRead > 0)
{
try
{
// send this chunk to the server. it is sent as a byte[] parameter, but the client and server have been configured to encode byte[] using MTOM.
requestStream.Write(Buffer , 0, BytesRead);
// sentBytes is only updated AFTER a successful send of the bytes. so it would be possible to build in 'retry' code, to resume the upload from the current SentBytes position if AppendChunk fails.
SentBytes += BytesRead;
// update the user interface
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
}
catch (Exception ex)
{
errors.Add("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
// rewind the filestream and keep trying
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("E rror occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the next chunk (if it exists) into the buffer. the while loop will terminate if there is nothing left to read
}
}
}
using (FtpWebResponse response = (FtpWebResponse)request.Ge tResponse( ))
{
if (errors.Count > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder( );
foreach (string str in errors)
{
sb.Append(str + System.Environment.NewLine ); //windows
//sb.Append(str + "<br />"); //web
}
throw new Exception("File upload completed, however there were errors: " + sb.ToString());
}
else
{
return String.Format("Upload File Complete, status {0}", response.StatusDescription );
}
}
}
/// <summary>
/// Returns a description of a number of bytes, in appropriate units.
/// e.g.
/// passing in 1024 will return a string "1 Kb"
/// passing in 1230000 will return "1.23 Mb"
/// Megabytes and Gigabytes are formatted to 2 decimal places.
/// Kilobytes are rounded to whole numbers.
/// If the rounding results in 0 Kb, "1 Kb" is returned, because Windows behaves like this also.
/// </summary>
public static string GetFileSize(long numBytes)
{
string fileSize = "";
if (numBytes > 1073741824)
fileSize = String.Format("{0:0.00} Gb", (double)numBytes / 1073741824);
else if (numBytes > 1048576)
fileSize = String.Format("{0:0.00} Mb", (double)numBytes / 1048576);
else
fileSize = String.Format("{0:0} Kb", (double)numBytes / 1024);
if (fileSize == "0 Kb")
fileSize = "1 Kb"; // min.
return fileSize;
}
my code above is based on the following:
http://www.codeproject.com/soap/MTOMWebServices.asp?df=100&forumid=250646&exp=0&fr=26&select=1893456
public string UploadFile(string ftpHost, string targetFolderOnHost, string filename, string ftpUsername, string ftpPword, bool returnUniqueNewFilename)
{
System.Collections.ArrayLi
string requestMethod = "";
string uploadPath = "";
// set up the host string to request. this includes the target folder and the target file name (based on the source filename)
if (returnUniqueNewFilename)
{
requestMethod = System.Net.WebRequestMetho
uploadPath = String.Format("{0}/{1}{2}"
}
else
{
requestMethod = System.Net.WebRequestMetho
uploadPath = String.Format("{0}/{1}{2}"
}
if (!uploadPath.ToLower().Sta
{
uploadPath = "ftp://" + uploadPath;
}
System.Net.FtpWebRequest request = (System.Net.FtpWebRequest)
request.UseBinary = true;
request.UsePassive = true;
request.Method = requestMethod;
request.Credentials = new System.Net.NetworkCredenti
// Copy the contents of the file to the request stream.
long FileSize = new System.IO.FileInfo(filenam
string FileSizeDescription = GetFileSize(FileSize); // e.g. "2.4 Gb" instead of 240000000000000 bytes etc...
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize]; // this buffer stores each chunk, for sending to the web service via MTOM
using (System.IO.Stream requestStream = request.GetRequestStream()
{
using (System.IO.FileStream fs = System.IO.File.Open(filena
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
// send the chunks to the web service one by one, until FileStream.Read() returns 0, meaning the entire file has been read.
while (BytesRead > 0)
{
try
{
// send this chunk to the server. it is sent as a byte[] parameter, but the client and server have been configured to encode byte[] using MTOM.
requestStream.Write(Buffer
// sentBytes is only updated AFTER a successful send of the bytes. so it would be possible to build in 'retry' code, to resume the upload from the current SentBytes position if AppendChunk fails.
SentBytes += BytesRead;
// update the user interface
string SummaryText = String.Format("Transferred
}
catch (Exception ex)
{
errors.Add("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
// rewind the filestream and keep trying
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("E
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the next chunk (if it exists) into the buffer. the while loop will terminate if there is nothing left to read
}
}
}
using (FtpWebResponse response = (FtpWebResponse)request.Ge
{
if (errors.Count > 0)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder(
foreach (string str in errors)
{
sb.Append(str + System.Environment.NewLine
//sb.Append(str + "<br />"); //web
}
throw new Exception("File upload completed, however there were errors: " + sb.ToString());
}
else
{
return String.Format("Upload File Complete, status {0}", response.StatusDescription
}
}
}
/// <summary>
/// Returns a description of a number of bytes, in appropriate units.
/// e.g.
/// passing in 1024 will return a string "1 Kb"
/// passing in 1230000 will return "1.23 Mb"
/// Megabytes and Gigabytes are formatted to 2 decimal places.
/// Kilobytes are rounded to whole numbers.
/// If the rounding results in 0 Kb, "1 Kb" is returned, because Windows behaves like this also.
/// </summary>
public static string GetFileSize(long numBytes)
{
string fileSize = "";
if (numBytes > 1073741824)
fileSize = String.Format("{0:0.00} Gb", (double)numBytes / 1073741824);
else if (numBytes > 1048576)
fileSize = String.Format("{0:0.00} Mb", (double)numBytes / 1048576);
else
fileSize = String.Format("{0:0} Kb", (double)numBytes / 1024);
if (fileSize == "0 Kb")
fileSize = "1 Kb"; // min.
return fileSize;
}
my code above is based on the following:
http://www.codeproject.com/soap/MTOMWebServices.asp?df=100&forumid=250646&exp=0&fr=26&select=1893456
ASKER
I wonder if it's a URI issue / how I'm formatting - I'll keep testing & that's why I was also asking for URI examples to make sure I'm on target. I understand escaping (\) or using @ for the string is important too...but I'm doing that.
The reason this stuff is tricky is (obviously) it's a combination of getting the FTP settings on the server side, settings for firewalls on the client & server & specific code which make a successful file upload.
I'm looking for specific sample code that worked for someone so that I can work backwards & determine which of the above settings I need to change on my end to make it work.
Here are others I tested: the first was great - good explanations.
http://www.ddj.com/dept/database/191601621?pgno=3
http://www.windowsdevcenter.com/pub/a/windows/2006/12/12/building-ftp-services-using-net-20.html?page=last
http://www.thescripts.com/forum/thread278208.html
http://tim.mackey.ie/FtpWebRequestWithProgressBarCFtp.aspx