Finding some problems copying a zip file from an FTP location. It is just copying and empty file so I think there is something wrong with my use of StreamReader or StreamWriter.
Here is the code:
//read through directory details response
string line = reader.ReadLine();
while (line != null)
{
if (line.EndsWith("zip")) //"d" = dir don't need "." or ".." dirs
{
FtpWebRequest downloadRequest = (FtpWebRequest)FtpWebRequest.Create("ftp://" + ftpHost + line); //new Uri("ftp://" + ftpServerIP + DestinationFolder + fileInf.Name));
downloadRequest.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["FilesUser"], ConfigurationManager.AppSettings["FilesPass"]);
downloadRequest.KeepAlive = false;
downloadRequest.UseBinary = true;
downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile;
string folderToWrite = HttpContext.Current.Server.MapPath("~/Routing/RoutingFiles/");
string folderToSave = HttpContext.Current.Server.MapPath("~/Routing/");
StreamReader downloadRequestReader = new StreamReader(downloadRequest.GetResponse().GetResponseStream());
DirectoryInfo downloadDirectory = new DirectoryInfo(folderToWrite);
FileInfo file = new FileInfo(Path.Combine(downloadDirectory.FullName, line));
if (!file.Exists)
{
StreamWriter writer = new StreamWriter(Path.Combine(folderToWrite, line), false);
writer.Write(downloadRequestReader.ReadToEnd());
using (var downloadResponseStream = response.GetResponseStream())
{
}
}
}
}
By the time it gets to the bottom of that section, the file has been copied but is empty so I don't think I'm reading the stream correctly for a zip file. Anyone any ideas? I've seen talk of FileStream being better for downloading Zip files, but I couldn't get that to work either.
Thanks.
Here is an example that downloads a file from an ftp.
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpAddr + "test.zip");
request.Credentials = new NetworkCredential(userName, password);
request.UseBinary = true; // Use binary to ensure correct dlv!
request.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
FileStream writer = new FileStream("test.zip", FileMode.Create);
long length = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[2048];
readCount = responseStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
writer.Write(buffer, 0, readCount);
readCount = responseStream.Read(buffer, 0, bufferSize);
}
responseStream.Close();
response.Close();
writer.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Edit I'm sorry for the error in previous code.
When correcting my previous code I found the following resource useful: example
Related
I'm not sure why my file is corrupted. I'm not using StreamReader which has been a common problem that most have had. It uploads successfully I just can't seem to find the issue on why the file is corrupted even after searching through the various solved stack overflow questions.
public ActionResult UploadFtpFile(HttpPostedFileBase promoImgFile)
{
bool isSavedSuccessfully = true;
string fileName = null;
string completeDPath = "xxxxx";
string username = "xxxx";
string password = "xxxxx";
FtpWebRequest ftpClient;
FtpWebRequest ftpRequest;
List<string> directories = new List<string>();
try
{
foreach (string fileItemName in Request.Files)
{
HttpPostedFileBase file = Request.Files[fileItemName];
fileName = file.FileName;
if (file != null && file.ContentLength > 0)
{
//Create FtpWebRequest object
ftpClient = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + completeDPath + "/" + fileName));
//Set request method
ftpClient.Method = WebRequestMethods.Ftp.UploadFile;
//Set Credentials
ftpClient.Credentials = new NetworkCredential(username, password);
//Opens a file to read
Stream objFile = file.InputStream;
//By default KeepAlive is true, where the control connection is not closed after a command is executed.
ftpClient.KeepAlive = true;
//Set the data transfer type
ftpClient.UseBinary = true;
//Set content length
ftpClient.ContentLength = file.ContentLength;
//Get Stream of the file
Stream objStream = ftpClient.GetRequestStream();
byte[] buffer = new byte[objFile.Length];
//Write file content
objStream.Write(buffer, 0, buffer.Length);
objStream.Close();
objFile.Close();
}
}
}
catch(Exception ex)
{
throw ex;
isSavedSuccessfully = false;
}
//return Json(new { promoImgFile = directories });
return RedirectToAction("Index", "Home", new { promoImgFile = directories });
}
It's this line right here:
Stream objFile = file.InputStream;
Years of learning, I figured out one thing that works:
MemoryStream ms = new MemoryStream();
file.InputStream.CopyTo(ms);
Then work off the MemoryStream.
Example (for text)
Docs: MSDN
The important part for your issue:
StreamReader sourceStream = new StreamReader("testfile.txt");
byte [] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
Example (for an image)
byte [] imageData = File.ReadAllBytes(imageSource);
request.ContentLength = imageData.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(imageData, 0, imageData.Length);
requestStream.Close();
So i have a file locally that needs to keep the same name. But when i upload the file to the FTP i want to rename it, or add some ekstra to the file name. here is how i upload the file.
string localPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string fileName = "//XmlDocument.xml";
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("ftp://000.000.000/Documents" + fileName);
requestFTPUploader.Credentials = new NetworkCredential(ftpUsername, ftpPassword);
requestFTPUploader.Method = WebRequestMethods.Ftp.UploadFile;
FileInfo fileInfo = new FileInfo(localPath + fileName);
FileStream fileStream = fileInfo.OpenRead();
int bufferLength = 2048;
byte[] buffer = new byte[bufferLength];
Stream uploadStream = requestFTPUploader.GetRequestStream();
int contentLength = fileStream.Read(buffer, 0, bufferLength);
while (contentLength != 0)
{
uploadStream.Write(buffer, 0, contentLength);
contentLength = fileStream.Read(buffer, 0, bufferLength);
}
uploadStream.Close();
fileStream.Close();
requestFTPUploader = null;
There is no relation whatsoever between the name of the file you're trying to upload and the name on the server you're uploading it to.
You can upload foo.jpg as bar.exe and no one will bat an eye.
So change this:
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("..." + fileName);
To this:
FtpWebRequest requestFTPUploader = (FtpWebRequest)WebRequest.Create("..." + ftpFileName);
And you're good to go.
I am trying to Zip files from ftp server(using C#) and save zip file somewhere in my Local pc.I managed a code that could zip a file. But I am not sure how to loop through the ftp to zip all the files (max I should Zip 100 files and Zipfile should not exceed 100 megabytes.
That is the code I used to connect to ftp and Zip 1 file. How I can Zip several Files?
public void ProcessZipRequest(string strQueueID, string strBatchID, string strFtpPath)
{
int intReportCnt = 0;
string strZipFileName = "Order-" + strBatchID + "-" + strQueueID + "-" + DateTime.Now.ToString("MM-dd-yyyy-HH-mm") + ".zip";
strZipFileName = SafeFileName(strZipFileName);
//MemoryStream ms = new MemoryStream();
FileStream ms = new FileStream(#"c:\ZipFiles\nitest.zip", FileMode.Create);
ZipOutputStream oZipStream = new ZipOutputStream(ms); // create zip stream
oZipStream.SetLevel(9); // maximum compression
intReportCnt += 1;
string strRptFilename;
if (strQueueID != null)
{
MemoryStream outputStream = new MemoryStream();
// Get file path
string ftpFilePath = #"ftp://12.30.228.20/AOTest/Images/Report/11/595/45694/62_s.jpg";
// That is where I get 1 file from ftp (How loop here?)
strRptFilename = ftpFilePath.Substring(ftpFilePath.LastIndexOf("/") + 1);
FtpWebRequest reqFTP = (FtpWebRequest)System.Net.WebRequest.Create(ftpFilePath);
reqFTP.UseBinary = true;
reqFTP.KeepAlive = false;
reqFTP.Credentials = new NetworkCredential("username", "password");
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
reqFTP.Proxy = null;
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 2048;
int readCount;
byte[] buffer = new byte[bufferSize];
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
outputStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
ftpStream.Close();
outputStream.Position = 0;
//Where I zip the files
ZipFile(ref outputStream, strRptFilename, ref oZipStream);
ftpStream.Close();
outputStream.Close();
if (response != null)
{
response.Close();
}
}
And that is ZipFile Method that zip the file:
public void ZipFile(ref MemoryStream msFile, string strFilename, ref ZipOutputStream oZipStream)
{
ZipEntry oZipEntry = new ZipEntry(strFilename);
oZipEntry.DateTime = DateTime.Now;
oZipEntry.Size = msFile.Length;
oZipStream.PutNextEntry(oZipEntry);
StreamUtils.Copy(msFile, oZipStream, new byte[4096]);
oZipStream.CloseEntry();
}
Have you considered using a foreach loop with a list.
Try something like
Filenamelist = new List <string>();
Then run a foreach loop to populate the list with your files. Something like
foreach (//listobject in //listname)
{
Filenamelist.Add(file.Name).
}
and from there run the same type of thing with a foreach loop to zip your
function.
Just a thought. Cheers!
I have a methode that copy folder structure from ftp to local folder and then copy all files that consists in them:
public void CreateDirectories()
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(Url);
request.Credentials = new NetworkCredential(Login, Pass);
request.Method = WebRequestMethods.Ftp.ListDirectory;
string soursePath = #"L:\Test";
StreamReader streamReader = new StreamReader(request.GetResponse().GetResponseStream());
string directoryName = streamReader.ReadLine();
while (directoryName != null)
{
//Create directories structure
if (directoryName.StartsWith("I") && !directoryName.Contains("p"))
{
string newPath = System.IO.Path.Combine(soursePath, directoryName);
if (!System.IO.Directory.Exists(newPath))
{
System.IO.Directory.CreateDirectory(newPath);
//get file list and invoke DownLoad(string directoryName, string fileName)
FtpWebRequest fileRequest = (FtpWebRequest)WebRequest.Create(Url + directoryName + "/");
fileRequest.Credentials = new NetworkCredential(Login, Pass);
fileRequest.Method = WebRequestMethods.Ftp.ListDirectory;
StreamReader fileStreamReader = new StreamReader(fileRequest.GetResponse().GetResponseStream());
string fileName = fileStreamReader.ReadLine();
while (fileName != null)
{
DownLoad(directoryName, fileName);
fileName = streamReader.ReadLine();
}
}
}
directoryName = streamReader.ReadLine();
}
request = null;
streamReader = null;
}
and the methode that copy current file:
public void DownLoad(string directoryName, string fileName)
{
string localPath = #"L:\Test\" + directoryName;
FtpWebRequest requestFileDownload = (FtpWebRequest)WebRequest.Create("ftp://ftp.equip.me/prod/" + directoryName + "/" + fileName);
requestFileDownload.Credentials = new NetworkCredential(Login, Pass);
requestFileDownload.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse responseFileDownload = (FtpWebResponse)requestFileDownload.GetResponse();
Stream responseStream = responseFileDownload.GetResponseStream();
FileStream writeStream = new FileStream(localPath + "\\" + fileName, FileMode.Create);
int Length = 2048;
Byte[] buffer = new Byte[Length];
int bytesRead = responseStream.Read(buffer, 0, Length);
while (bytesRead > 0)
{
writeStream.Write(buffer, 0, bytesRead);
bytesRead = responseStream.Read(buffer, 0, Length);
}
responseStream.Close();
writeStream.Close();
requestFileDownload = null;
responseFileDownload = null;
}
But in line Stream responseStream = responseFileDownload.GetResponseStream(); it stop for nearly 40 seconds and then throw an exeption of timeout, and no one file has not been saved (file is small - 50 kb)
The first thing that you should try is to turn passive mode off since this is automatically blocked by most firewalls, but is the default mode of operation for ftpWebRequest.
Just below this line:
requestFileDownload.Method = WebRequestMethods.Ftp.DownloadFile;
and this one:
requestFileDownload.UsePassive = false;
I think I have some memory issue with a function that should download a file from ftp server. The reason that I think it's a memory thing is because it works fine during debug (maybe it gives the garbage collector more time). Yet I thought that the using should solve this...
Just to be clear the function works when called once yet calling it several times in a for loop invokes the err message: 550 The specified network name is no longer available.
Please help
Asaf
private void downloadFile(string sourceFile, string targetFolder)
{
string remoteFile = sourceFile.Replace("\\","//");
string localFolder = targetFolder + "\\" + sourceFile.Substring(sourceFile.LastIndexOf("\\")+1);
string filename = "ftp://" + ftpServerIP + "//" + remoteFile;
FtpWebRequest ftpReq = (FtpWebRequest)WebRequest.Create(filename);
ftpReq.Method = WebRequestMethods.Ftp.DownloadFile;
ftpReq.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
ftpReq.UseBinary = true;
ftpReq.Proxy = null;
ftpReq.KeepAlive = false; //'3. Settings and action
try
{
using (System.Net.FtpWebResponse response = (System.Net.FtpWebResponse)(ftpReq.GetResponse()))
{
using (System.IO.Stream responseStream = response.GetResponseStream())
{
using (System.IO.FileStream fs = new System.IO.FileStream(localFolder, System.IO.FileMode.Create))
{
Byte[] buffer = new byte[2047];
int read = 0;
do
{
read = responseStream.Read(buffer, 0, buffer.Length);
fs.Write(buffer, 0, read);
} while (read == 0);
responseStream.Close();
fs.Flush();
fs.Close();
}
responseStream.Close();
}
response.Close();
}
}
catch (WebException ex)
{
FtpWebResponse response = (FtpWebResponse)ex.Response;
Console.Out.WriteLine(response.StatusDescription);
}
}
There's a bug in the read loop that causes large files to be truncated. Use:
int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) != 0)
{
fs.Write(buffer, 0, read);
}
With that change in place I was able to download a number of large files via FTP without encountering exceptions.