Reputation: 1279
I wonder if this FtpWebRequest goes wrong and, it goes to the catch event. I have seen an example code where they posted what I have uncommented in the catch event, - to clean up the resources.
But I don't know what is the proper way to do that in this scenario? Should I just put all of those to: = null; or is this wrong to do? What is the proper way to do it?
cleanUp(sourceStream, ref response, ref requestStream, ref request);
void uploadimage()
{
String sourceimage = "C:/ESD/image_2.jpg";
Task<bool> task = FtpUploadFile(sourceimage);
if (task.IsFaulted == false)
{
MessageBox.Show(task.Result.ToString());
}
}
private Task closeRequestStreamAsync(Stream requestStream) { return Task.Run(() => { requestStream.Close(); }); }
public async Task<bool> FtpUploadFile(string filename)
{
//if exception occurs we want to be able to close these
FtpWebResponse response = null;
FtpWebRequest request = null;
FileStream sourceStream = null;
Stream requestStream = null;
try
{
bool isimage = false; String ext = Path.GetExtension(filename);
if (ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp") { isimage = true; }
request = (FtpWebRequest)WebRequest.Create("ftp://someurl.com/Folder1/test1.jpg");
request.UsePassive = true;
if (isimage == true) { request.UseBinary = true; } //for images
if (isimage == false) { request.UseBinary = false; } //for text
request.KeepAlive = true; //keep the connection open
request.Method = WebRequestMethods.Ftp.UploadFile;
request.ConnectionGroupName = "Group1";
request.ServicePoint.ConnectionLimit = 4;
//These are the credentials.
request.Credentials = new NetworkCredential("username", "password");
sourceStream = File.OpenRead(filename);
byte[] buffer = new byte[sourceStream.Length];
await sourceStream.ReadAsync(buffer, 0, buffer.Length);
sourceStream.Close();
requestStream = await request.GetRequestStreamAsync();
await requestStream.WriteAsync(buffer, 0, buffer.Length);
//MPM This is the call that takes the time
await closeRequestStreamAsync(requestStream);
//response = (FtpWebResponse)request.GetResponse();
WebResponse responseWeb = await request.GetResponseAsync();
response = (FtpWebResponse)responseWeb;
if (response.StatusDescription.Contains("226"))
{
//This means that we successfully have uploaded the file!
}
response.Close();
return true;
}
catch (Exception ex)
{
string errMSG = string.Format("Upload File failed, exception: {0}", ex.Message);
//cleanUp(sourceStream, ref response, ref requestStream, ref request);
return false;
}
}
Upvotes: 0
Views: 210
Reputation: 131364
To ensure the web request, response and stream objects are closed even if an exception occurs, they should be defined in a using
block.
The code can be simplified to :
var ext = Path.GetExtension(filename);
var imageExtensions=new[]{".jpg",".jpeg",".png",".gif",".bmp"};
var isimage = imageExtensions.Contains(ext);
var request = (FtpWebRequest)WebRequest.Create("ftp://someurl.com/Folder1/test1.jpg");
request.UseBinary =isimage;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.ConnectionGroupName = "Group1";
request.ServicePoint.ConnectionLimit = 4;
//These are the credentials.
request.Credentials = new NetworkCredential("username", "password");
using(var sourceStream = File.OpenRead(filename))
using(var requestStream = await request.GetRequestStreamAsync())
{
await sourceStream.CopyToAsync(requestStream);
}
using(var responseWeb = await request.GetResponseAsync())
{
var response = (FtpWebResponse)responseWeb;
if (response.StatusDescription.Contains("226"))
{
return true;
}
}
.....
I removed the KeepAlive and UsePassive setters because true
is their default value.
A WebRequest by itself doesn't hold any resources so it doesn't implement IDisposable. The connection to the server is made when GetRequestStream()
is called. The values that need disposing/closing are sourceStream
, requestStream
and responseWeb
.
Upvotes: 1