Prevent from another process to access the same ftp stream - c#

I'm trying to figure out how can I prevent access to the same ftp stream while I'm still writing to the ftp from another process/computer.
this is the code I try:
internal static bool WriteFileToServer(string urlToWriteOn, string strAllContent)
{
Uri ServerUri = new Uri(urlToWriteOn);
if (ServerUri.Scheme != Uri.UriSchemeFtp)
return false;
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ServerUri);
request.Method = WebRequestMethods.Ftp.UploadFile;
byte[] ContentsToWrite = Encoding.UTF8.GetBytes(strAllContent);
request.ContentLength = ContentsToWrite.Length;
request.Credentials = new NetworkCredential(UserID, Password);
request.UsePassive = false;
request.KeepAlive = false;
Stream requestStream = request.GetRequestStream();
requestStream.Write(ContentsToWrite, 0, ContentsToWrite.Length);
System.Threading.Thread.Sleep(10000);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
response.Close();
return true;
}
I made 2 threads that access the function at the same time and both of them stop in the sleep line after they wrote to the ftp (before the close part).
For the test, the first thread wrote 10,000 lines and the second thread wrote 500 lines.
In fact, the first thread is making new file on the ftp and write all the lines and then comes the other thread and rewrite on the first 500 lines (the other 9,500 lines from the first thread keep existing)
I would expect from the second thread to throw an exception, but its not.
I was solving the problem if the code of writing to the ftp was from the same application, but it's going to be written from 2 different computers and I don't want the other computer write to the ftp file simultaneously.

I don't believe you are hoping to accomplish is possible from the client side. My guess is that the better approach would be to write to a 'random' file name or a with a ".inprogress" extension or some such, and then rename the file appropriately once the upload is complete.

Related

C# Ftp uploading when network break, how to resume? [duplicate]

I am using below code (C# .NET 3.5) to upload a file:
FtpWebRequest request =
(FtpWebRequest)WebRequest.Create("ftp://someweb.mn/altanzulpharm/file12.zip");
request.Method = WebRequestMethods.Ftp.UploadFile;
request.KeepAlive = true;
request.UseBinary = true;
request.Credentials = new NetworkCredential(username, password);
FileStream fs = File.OpenRead(FilePath);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
fs.Close();
Stream ftpstream = request.GetRequestStream();
ftpstream.Write(buffer, 0, buffer.Length);
ftpstream.Close();
But the upload breaks when internet interrupted. Interruption occurs for a very small amount of time, almost a millisecond. But uploading breaks forever!
Is it possible to continue or resume uploading after interruption of internet?
I don't believe FtpWebRequest supports re-connection after losing connection. You can resume upload from given position if server supports it (this support is not required and presumably less common that retry for download).
You'll need to set FtpWebRequet.ContentOffset upload. Part of sample from the article:
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.ContentOffset = offset;
Internal details of restore in FTP protocol itself - RFC959: 3.5 - Error recovery and restart. Question showing retry code for download - Downloading from FTP with c#, can't retry when fail
The only way to resume transfer after a connection is interrupted with FtpWebRequest, is to reconnect and start writing to the end of the file.
For that use FtpWebRequest.ContentOffset.
A related question for upload with full code (although for C#):
How to download FTP files with automatic resume in case of disconnect
Or use an FTP library that can resume the transfer automatically.
For example WinSCP .NET assembly does. With it, a resumable upload is as trivial as:
// Setup session options
var sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
HostName = "ftp.example.com",
UserName = "user",
Password = "mypassword"
};
using (var session = new Session())
{
// Connect
session.Open(sessionOptions);
// Resumable upload
session.PutFileToDirectory(#"C:\path\file.zip", "/home/user");
}
(I'm the author of WinSCP)

If I read from a stream from WebRequest.GetResponseStream am I reading from memory or the network

I have the following code that downloads a file from an FTP server:
var req = (FtpWebRequest)WebRequest.Create(ftp_addr + file_path);
req.Credentials = new NetworkCredential(...);
req.Method = WebRequestMethods.Ftp.DownloadFile;
using (var resp = req.GetResponse())
using (var strm = resp.GetResponseStream())
using (var mem_strm = new MemoryStream())
{
//The Web Response stream doesn't support seek, so we have to do a buffered read into a memory stream
byte[] buffer = new byte[2048];
int red_byts = 0;
do
{
red_byts = strm.Read(buffer, 0, 2048);
mem_strm.Write(buffer, 0, red_byts);
}
while (strm.CanRead && red_byts > 0);
//Reset the stream to position 0 for reading
mem_strm.Position = 0;
//Now I've got a mem stream that I can use
}
Since the raw stream returned from "GetResponseStream" cannot be read or sought (cannot perform a seek on it). It seems to me that this code is actually performing a request to the FTP server for the next chunk of the file and copying it into memory. Am I correct, or is the entire response downloaded when you can GetResponseStream?
I just want to know so I can correctly apply awaits with ReadAsync calls in asynchronous methods that make use of FTP downloading. My intuition tells me to change the line:
red_byts = strm.Read(...);
to
red_byts = await strm.ReadAsync(...);
The documentation of WebRequest.GetResponseStream doesn't seem to specify, nor does the documentation for FtpWebRequest.GetResponseStream.
The raw stream should be a network stream; to verify this, check out strm.GetType().Name.
It seems to me that this code is actually performing a request to the FTP server for the next chunk of the file and copying it into memory. Am I correct, or is the entire response downloaded when you can GetResponseStream?
Neither.
It is not sending separate requests for each call to Read/ReadAsync; rather, there is only one request, and the stream represents the body of the one response.
It is also not downloading the entire response before returning from GetResponseStream. Rather, the stream represents the download. Some buffering is going on - as the server is sending data, the network stack and the BCL are reading it in for you - but there's no guarantee that it's download by the time you start reading the stream.
I just want to know so I can correctly apply awaits with ReadAsync calls in asynchronous methods that make use of FTP downloading. My intuition tells me to [use async]
Yes, you should use asynchronous reads. If some data is already buffered, they may complete synchronously; otherwise, they will need to wait until the server sends more data.

ftpWebReponse (ListDirectory) FTP approved log in process, but not returning folder data

I've been experimenting with using Visual C# to connect to a remote FTP server, and list the folders on the server. Ultimately, I'm trying to figure out how to automatically upload a file to this server with the click of a button. I figured my first step would be to see how the folders are structured on the remote FTP server. However, when I try to view the results passed in debug, it appears to be empty, although I didn't receive any errors from the process, and the parameters in debug make it look like I was successfully logged in. I also received the file transfer complete message 226 in the response data. Here's the latest code I have tried, although I have tried various things in the FtpWebRequest function. If I turn off UsePassive, it sits there forever and I never get a response back from the server. Does anyone have any ideas on a setting that might be causing this or some parameter that might need to be set?
private void button4_Click(object sender, EventArgs e)
{
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://sampleftpplace.com/");
ftpRequest.UseBinary = true;
ftpRequest.Credentials = new NetworkCredential("username", "password");
ftpRequest.EnableSsl = true;
ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory;
ftpRequest.Proxy = null;
ftpRequest.Timeout = -1;
ftpRequest.KeepAlive = false;
//ftpRequest.UsePassive = false;
FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse();
StreamReader streamReader = new StreamReader(response.GetResponseStream());
List<string> directories = new List<string>();
string line = streamReader.ReadLine();
while (!string.IsNullOrEmpty(line))
{
directories.Add(line);
line = streamReader.ReadLine();
}
streamReader.Close();
}
When the "string line = streamReader.Readline();" is executed, the variable "line" is null. All I am really after is to see what folders are available so I can see how the original programmer of the FTP server structured their folders, and what naming convention they used. Is this possible if that programmer isn't available any more?
I just had a crazy thought, and it turned out that it worked! Basically, I changed the first couple of lines to read like this:
Uri uri = new Uri("ftp://sampleftpplace.com//");
FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(uri);
First, I used the command Uri. Not sure if that matters or not, but what really mattered was the 2nd "/" in the URL address. I think the server didn't see it as the root directory until I added this. Once I put that in, I'm seeing the folders now. Thanks!

C# ftp EndGetRequestStream

Hello i have a problem with my FTP Server.
Let me explain:
I made a tool which uploads a .png file to my FTP.
When i upload 2 images with some delay inbetween ofcoursse.. And try to upload the third one. I get a timeout error. I think this is because i need to end the stream. But i am not sure how to use FtpWebRequest.EndGetRequestStream. Does anybody has any clue?
Here is my code if you need it:
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create("ftp://www.mysite.com/public_html/" + name);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential("MyFTPUsername", "MyFTPPassword");
request.UseBinary = true;
request.UsePassive = true;
request.KeepAlive = true;
shot = sc.CaptureWindow(HandleID);// Here i take a screenshot of my active window
shot.Save(request.GetRequestStream(), ImageFormat.Png);// Here i upload it to the FTP
request.EndGetRequestStream();// <-- - Now i (think) need to end the stream. But i am not sure how to use the parameters
Thanks!
( Please let me know if i am not clear enough! )
May be calling of request.GetRequestStream() instead of request.EndGetRequestStream() is all you need?
UPDATE:
Sorry, I mean calling of request.GetResponse() instead of request.EndGetRequestStream().

How do I directly upload the images to FTP from the given image path(Live URL)

I am working on the task that, I need to upload the images to particular FTP by using C# coding from given live path.
At the moment I done it, but to upload images on FTP I take round trip of (download the images
on local and then upload it to live by using code).
I want the solution to directly upload images to to ftp without downloading it.
eg. From given path http://www.globalgear.com.au/products/bladesbook_sml.jpg
I need this image to upload.
hello, I am rectifying my question more, I want to fetch Small and large images from this URL(globalgear.com.au/productfeed.xml) and upload directly to FTP without downloading it on local. –
Please suggest any solution.
Thanks
Chetan
Perhabs this will work:
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create("ftp://www.contoso.com/test.htm");
request.Method = WebRequestMethods.Ftp.UploadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe#contoso.com");
// Copy the contents of the file to the request stream.
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();
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Console.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
response.Close();

Categories