How to upload large files to FTP server in ASP MVC - c#

I am developing an ASP MVC website.
Now i need to upload files(.zip files) to my FTP server. For uploading i use this code.
This code uploads only those files which has size < 10 Mb.
for Example: when i upload a file with 150 MB size with this code it get damaged and the file size changed to 300 MB on my Ftp Server.
So can any one help me..
byte[] fileBytes = null;
//Read the FileName and convert it to Byte array.
string filename = Path.GetFileName(FileUpload1.FileName);
using (StreamReader fileStream = new StreamReader(FileUpload1.InputStream))
{
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd());
fileStream.Close();
}
try
{
//Create FTP Request.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftp + ftpFolder + "/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
//Enter FTP Server credentials.
request.Credentials = new NetworkCredential(ftpUName, ftpPWord);
request.ContentLength = fileBytes.Length;
request.UsePassive = true;
request.UseBinary = true;
request.ServicePoint.ConnectionLimit = fileBytes.Length;
request.EnableSsl = false;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileBytes, 0, fileBytes.Length);
requestStream.Close();
}
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
}
catch (WebException ex)
{
throw new Exception((ex.Response as FtpWebResponse).StatusDescription);
}

Add this to your web.config
<httpRuntime maxRequestLength="whatever value you need in kb max value is 2,147,483,647 kb" relaxedUrlToFileSystemMapping="true" />
under system.web section
the default is 4 mb size limit
Details here

It probably gets corrupt, because you are reading the data with utf8 encoded. You should read it in binary format.
Don't use:
using (StreamReader fileStream = new StreamReader(FileUpload1.InputStream))
{
fileBytes = Encoding.UTF8.GetBytes(fileStream.ReadToEnd());
fileStream.Close();
}
You have to use File.ReadAllBytes or a BinaryReader(Stream)
https://msdn.microsoft.com/en-us/library/system.io.file.readallbytes(v=vs.110).aspx
https://msdn.microsoft.com/de-de/library/system.io.binaryreader(v=vs.110).aspx
for your example:
byte[] fileBytes = File.ReadAllBytes(Path.GetFileName(FileUpload1.FileName));
try
{
//Create FTP Request.
FtpWebRequest request = (FtpWebRequest)...

Related

Download CSV file with WebClient in C# but the size of file is less than when download with browser

I have a link that returns a CSV file. When I open it in a browser (Chrome, Firefox,...) the size of file that's downloaded is 86 KB, but when I want to download it with the code below, the size is just 25 KB and when I open the downloaded file it doesn't have correct data (means no columns and can't read data)
You can try it in browser and code
http://tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=43283802997035462
string url = "http://tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=43283802997035462";
WebClient wc = new WebClient();
wc.DownloadFile(url, "111.csv");
webClient is returning you zip file instead of plain text /csv file
I changed wc output file extension to zip and it is working...
zip will contain file that you specified in argument
screenshot from RestClient
As Akshay Sandhu pointed out the downloaded file is compressed with the gzip encoding and that is why it appears as corrupted when trying to open it as a csv.
To download the file and automatically decode it please refer to these two SO answers.
First download the file using the HttpWebRequest class instead of the WebClient class as done here:
How to Download the File using HttpWebRequest and HttpWebResponse class(Cookies,Credentials,etc.)
Then make sure the file is automatically decompressed. Check this out
Automatically decompress gzip response via WebClient.DownloadData
Here is the working code:
string url = "http://tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=43283802997035462";
string path = "111.csv";
using (FileStream fileStream = new FileStream(path, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write))
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Get;
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
const int BUFFER_SIZE = 16 * 1024;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var buffer = new byte[BUFFER_SIZE];
int bytesRead;
do
{
bytesRead = responseStream.Read(buffer, 0, BUFFER_SIZE);
fileStream.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
}
}
}
You need to decompress the gzip, before you read it to file.
var url = new Uri("http://tsetmc.com/tsev2/data/Export-txt.aspx?t=i&a=1&b=0&i=43283802997035462");
var path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var fileName = "111.csv";
using (WebClient wc = new WebClient())
using (Stream s = File.Create(Path.Combine(path, fileName)))
using (GZipStream gs = new GZipStream(wc.OpenRead(url), CompressionMode.Decompress))
{
//Saves to C:\Users\[YourUser]\Desktop\111.csv
gs.CopyTo(s);
}

How can I upload Image ftp server asp.net mvc

I want to upload image by using ftp account. My code is like this. But when I choose image and submit, It says me "Could not find file 'C:\Program Files (x86)\IIS Express\picture.jpg'." I know my image is on my desktop and I choose from there. If I copy my image manually this IIS folder, it will upload but this is not sensible. I must choose my image where I want. But it is looking for in IIS Express folder.
[HttpPost, ValidateInput(false)]
public ActionResult Insert(Press model, HttpPostedFileBase uploadfile)
{
...........
...........
...........
...........
if (uploadfile.ContentLength > 0)
{
string fileName = Path.Combine(uploadfile.FileName);
var fileInf = new FileInfo(fileName);
var reqFtp =
(FtpWebRequest)
FtpWebRequest.Create(
new Uri("ftp://ftp.adres.com" + fileInf.Name));
reqFtp.Credentials = new NetworkCredential(username, password);
reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.UploadFile;
reqFtp.UseBinary = true;
reqFtp.ContentLength = uploadfile.ContentLength;
int bufferlength = 2048;
byte[] buff = new byte[bufferlength];
int contentLen;
FileStream fs = fileInf.OpenRead();
try
{
Stream strm = reqFtp.GetRequestStream();
contentLen = fs.Read(buff, 0, bufferlength);
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
contentLen = fs.Read(buff, 0, bufferlength);
}
strm.Close();
fs.Close();
}
catch (Exception ex)
{
}
}
...........
...........
...........
...........
return View();
}
}
I found a solution for my problem and I want to share here, maybe a person can benefit
void UploadToFtp(HttpPostedFileBase uploadfile)
{
var uploadurl = "ftp://ftp.adress.com/";
var uploadfilename = uploadfile.FileName;
var username = "ftpusername";
var password = "ftppassword";
Stream streamObj = uploadfile.InputStream;
byte[] buffer = new byte[uploadfile.ContentLength];
streamObj.Read(buffer, 0, buffer.Length);
streamObj.Close();
streamObj = null;
string ftpurl = String.Format("{0}/{1}", uploadurl, uploadfilename);
var requestObj = FtpWebRequest.Create(ftpurl) as FtpWebRequest;
requestObj.Method = WebRequestMethods.Ftp.UploadFile;
requestObj.Credentials = new NetworkCredential(username, password);
Stream requestStream = requestObj.GetRequestStream();
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Flush();
requestStream.Close();
requestObj = null;
}
Ensure the value in fileName is what you are expecting here:
string fileName = Path.Combine(uploadfile.FileName);
You most likely need to pass the path as a string, as well as the filename into the Combine method.
string fileName = Path.Combine(varFilePath, uploadfile.FileName);
Path.Combine expects an array of strings to combine: https://msdn.microsoft.com/en-us/library/system.io.path.combine%28v=vs.110%29.aspx
How to upload file by ftp using Asp.net MVC.
View
<form method="post" enctype="multipart/form-data">
<input type="file" id="postedFile" name="postedFile" />
<input type="submit" value="send" />
</form>
Controller ActionResult
[HttpPost]
public ActionResult Index(HttpPostedFileBase postedFile)
{
//FTP Server URL.
string ftp = "ftp://ftp.YourServer.com/";
//FTP Folder name. Leave blank if you want to upload to root folder.
string ftpFolder = "test/";
byte[] fileBytes = null;
string ftpUserName = "YourUserName";
string ftpPassword = "YourPassword";
//Read the FileName and convert it to Byte array.
string fileName = Path.GetFileName(postedFile.FileName);
using (BinaryReader br = new BinaryReader(postedFile.InputStream))
{
fileBytes = br.ReadBytes(postedFile.ContentLength);
}
try
{
//Create FTP Request.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftp + ftpFolder + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
//Enter FTP Server credentials.
request.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
request.ContentLength = fileBytes.Length;
request.UsePassive = true;
request.UseBinary = true;
request.ServicePoint.ConnectionLimit = fileBytes.Length;
request.EnableSsl = false;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(fileBytes, 0, fileBytes.Length);
requestStream.Close();
}
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
}
catch (WebException ex)
{
throw new Exception((ex.Response as FtpWebResponse).StatusDescription);
}
return View();
}
For upload large files you can add this line to your web.config
Thanks to Karthik Ganesan
<httpRuntime maxRequestLength="whatever value you need in kb max value is 2,147,483,647 kb" relaxedUrlToFileSystemMapping="true" />
under system.web section the default is 4 mb size limit

How to save csv to memory and then ftp?

I am currently creating a CSV file and then I ftp that file.
This is working fine. However, I dont want to save the csv file, i want to create it to memory and then ftp it.
This is my current code:
private void Csv()
{
CsvExport eftExport = new CsvExport();
eftExport.AddRow();
eftExport["customer_reference"] = "Ref";
eftExport["landline"] = "01234567890";
string url = "C:/Content/Cms/DD/";
string fileName = "file.csv";
eftExport.ExportToFile(url + fileName);
this.FtpFile(url, fileName);
}
private void FtpFile(string url, string fileName)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://url.co.uk/" + fileName);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential ("Administrator", "pass");
StreamReader sourceStream = new StreamReader(url + fileName);
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();
}
but in stead of doing eftExport.ExportToFile(url + fileName); i dont want it to save to machine??
Use this to but it into a byte array:
byte[] buffer = eftExport.ExportToBytes();
Now:
requestStream.Write(buffer, 0, buffer.Length);
Use the ExportToBytes() function of your CsvExport class.
Then change your FtpFile() to accept a byte array and remove the stream reader
you should end up with quite a bit less code :)
If your CsvExport type has an ExportToStream or similar simply use that create the stream that you subsequently write to the requestStream.

Multiple threads uploading files to filezilla ftp server returns error 550 File unavailable

Problem: When i ftp upload only one file at a time, the files are uploaded fine, But when i use multiple Background workers to upload files to ftp server i get exception:
ex {"The remote server returned an error: (550) File unavailable
(e.g., file not found, no access)."} System.Exception
{System.Net.WebException}
And only Some of the files get uploaded. I am pretty sure the file exits at that location, infact in another run the file it was complaining about that does not exist is downloaded but the error shifts on another file.
Code Description:
In below code i am downloading a file from one ftp server and putting it on another. This code is inside a BackgroundsWorker_DoWork Method. Background Workers are being created inside a loop.
void imageDownloadWorker_DoWork(object sender, DoWorkEventArgs e)
{
string[] ftpInfo = (string[])e.Argument;
try
{
///////////////////////////Downloading///////////////////////////////////////
string uri = String.Format("ftp://{0}/{1}/images/{2}", ftpInfo[1], ftpInfo[2], ftpInfo[5]);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
request.Credentials = new NetworkCredential(ftpInfo[3], ftpInfo[4]);
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream ftpStream = response.GetResponseStream();
long cl = response.ContentLength;
int bufferSize = 4096;
int readCount = 0;
byte[] buffer = new byte[bufferSize];
MemoryStream memStream = new MemoryStream();
readCount = ftpStream.Read(buffer, 0, bufferSize);
while (readCount > 0)
{
memStream.Write(buffer, 0, readCount);
readCount = ftpStream.Read(buffer, 0, bufferSize);
}
response.Close();
///////////////////////////Uploading///////////////////////////////////////
string uri1 = String.Format("ftp://{0}/{1}/{2}", "127.0.0.1", string.Empty, ftpInfo[5]);
FtpWebRequest request1 = (FtpWebRequest)WebRequest.Create(uri1);
request1.Credentials = new NetworkCredential("user", "password");
request1.KeepAlive = false;
request1.Method = WebRequestMethods.Ftp.UploadFile;
request1.UseBinary = true;
request1.ContentLength = memStream.Length;
int buffLength = 4096;
byte[] buff = new byte[buffLength];
int contentLen;
// Stream to which the file to be upload is written
Stream strm = request1.GetRequestStream();
memStream.Seek(0, SeekOrigin.Begin);
contentLen = memStream.Read(buff, 0, buffLength);
// Till Stream content ends
while (contentLen != 0)
{
// Write Content from the file stream to the FTP Upload Stream
strm.Write(buff, 0, contentLen);
contentLen = memStream.Read(buff, 0, buffLength);
}
// Close the file stream and the Request Stream
strm.Close();
ftpStream.Close();
memStream.Close();
}
catch(Exception ex)
{
MessageBox.Show("While Downloading File " + ftpInfo[5] + " " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
e.Result = null;
return;
}
Related Thread
Edit:
In File Zilla Server there is an option General Settings>Perfomance Settings>Number of Threads i have set that to 20 it didnt make any difference.
There maybe nothing wrong with your code. That error is a Permissions error.
Complete stab in the dark, but does the upload target server have a connection per IP limit? If so you may be falling foul of this by exceeding the concurrent connection limit from a single IP address.

FTP Changing PGP File During Transfer in C#

I have PGP files that I've verified as being valid, but at some point during the FTP upload, they become corrupt. When retrieved, I get an error message stating "Found no PGP information in these file(s)."
For what it's worth, the PGP is version 6.5.8, but I think that this is unimportant, as the files seem alright before they're uploaded.
My code is as follows for the file transfer, is there a setting or field that I've missed?
static void FTPUpload(string file)
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://ftp.itginc.com" + "/" + Path.GetFileName(file));
request.UseBinary = true;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ApplicationSettings["Username"], ApplicationSettings["Password"]);
StreamReader sr = new StreamReader(file);
byte[] fileContents = Encoding.UTF8.GetBytes(sr.ReadToEnd());
sr.Close();
request.ContentLength = fileContents.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse resp = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload file complete, status {0}", resp.StatusDescription);
resp.Close();
string[] filePaths= Directory.GetFiles(tempPath);
foreach (string filePath in filePaths)
File.Delete(filePath);
}
Any help is appreciated
Hmmmm try not reading it into a byte array and instead doing something like this
using (var reader = File.Open(source, FileMode.Open))
{
var ftpStream = request.GetRequestStream();
reader.CopyTo(ftpStream);
ftpStream.Close();
}
PGP encodes data to binary stream, so your reading it via StreamReader and UTF8 probably breaks the data. FTP is unlikely to alter the data as you explicitly binary mode (though UseBinary is true by default so your setting should not do anything at all).

Categories

Resources