0

I need to prevent existing files being overwritten (by this code, don't care about other ftp code overwriting it), I thought one way might be to upload them as readonly files, anyone able to do this, or other suggestion?

This is my simple uploader based on this msdn example:

public class FtpUploader
{
    private readonly string _root;

    public FtpUploader(string root)
    {
        _root = root;
        Credentials = new NetworkCredential("anonymous", "");
    }

    public NetworkCredential Credentials { get; set; }

    public async Task<bool> UploadAsync(string fileName, byte[] fileContents)
    {
        var doc = Path.Combine(_root, fileName);

        var request = (FtpWebRequest) WebRequest.Create(doc);
        request.Method = WebRequestMethods.Ftp.UploadFile;

        request.Credentials = Credentials;

        request.ContentLength = fileContents.Length;
        using (var requestStream = request.GetRequestStream())
        {
            await requestStream.WriteAsync(fileContents, 0, fileContents.Length);
        }

        using (var response = (FtpWebResponse) await request.GetResponseAsync())
        {
            Console.WriteLine("Upload File Complete, status {0}", response.StatusCode);
            return response.StatusCode == FtpStatusCode.ClosingData;
        }
    }
}

Used like this: I'd like the file to not get overwritten and to return false from upload (or throw some exception)

byte[] fileContents = Encoding.UTF8.GetBytes("Hello world!");
var res1 = await new FtpUploader(root).UploadAsync("hello.txt", fileContents);

fileContents = Encoding.UTF8.GetBytes("Should not get set to this!");
var res2 = await new FtpUploader(root).UploadAsync("hello.txt", fileContents);

I've tried WebRequestMethods.Ftp.UploadFileWithUniqueName which would be fine if there is a second step to rename/move easily? And get fail from rename/move.

weston
  • 54,145
  • 21
  • 145
  • 203

2 Answers2

1

I think you should check if the File exists.

You can have a look at this example: Stackoverflow example

I hope this helps you!

Community
  • 1
  • 1
whymatter
  • 755
  • 8
  • 18
  • Thanks, but that introduces a race condition, two threads can see that the file does not exist and both continue to create file. One will overwrite the other. – weston Jul 09 '15 at 15:55
0

I can upload and rename in two steps. This solves another problem; the listener will must not detect the new file before it is completely uploaded.

But still interested in other approaches.

public class FtpUploader
{
    private readonly string _root;

    public FtpUploader(string root)
    {
        _root = root;
        Credentials = new NetworkCredential("anonymous", "");
    }

    public NetworkCredential Credentials { get; set; }

    public async Task<bool> UploadAsync(string fileName, byte[] fileContents)
    {
        //var doc = Path.Combine(_root, fileName);

        var request = (FtpWebRequest) WebRequest.Create(_root);
        request.Method = WebRequestMethods.Ftp.UploadFileWithUniqueName;

        request.Credentials = Credentials;

        request.ContentLength = fileContents.Length;
        using (var requestStream = request.GetRequestStream())
        {
            await requestStream.WriteAsync(fileContents, 0, fileContents.Length);
        }

        using (var response = (FtpWebResponse) await request.GetResponseAsync())
        {
            Console.WriteLine("Upload File Complete, status {0}", response.StatusCode);
            Console.WriteLine(response.ResponseUri);

            if (response.StatusCode != FtpStatusCode.ClosingData) return false;

            try
            {
                return await Rename(response.ResponseUri, fileName);
            }
            catch (WebException)
            {
                return false;
            }
        }
    }

    private async Task<bool> Rename(Uri newUri, string newFileName)
    {
        var request = (FtpWebRequest) FtpWebRequest.Create(newUri);
        request.Proxy = null;
        request.Credentials = Credentials;

        request.Method = WebRequestMethods.Ftp.Rename;
        request.RenameTo = newFileName;
        using (var response = (FtpWebResponse) await request.GetResponseAsync())
        {
            Console.WriteLine("Rename File Complete, status {0}", response.StatusCode);
            Console.WriteLine(response.ResponseUri);

            return response.StatusCode == FtpStatusCode.FileActionOK;
        }
    }
}
weston
  • 54,145
  • 21
  • 145
  • 203