Connecting to cloud using C# WebDav

Hi Tomas,

You need to add some error handling there then. Depending on the directory you redirected to which was in my sample “path/path2/subpath”, there may or may not be any collections (sub-folders).

I don’t know if it is possible to download the entire directory at once using this library. You could attempt it though. FolderFiles is perhaps a rather non-fitting name, as you get ‘items’ back (which is either a folder or file). Just make sure you select a folder item and see if you can download it.

What kind of error handling do you mean? The class you wrote to me a few days back couls be edited to IDisposable. Then it requires the function Dispose inside the class. But here is the question - what am I disposing exactly? The called class itself or what?

After thia problem is solved, are you suggesting I should download folder’s files one by one? Wouldn’t it be much less complicated if I just uploaded .rar file instead of the folder. Would it even count as file?

Here is the problem:

’PropfindResponse’ does not contain a definition for ‘FirstOrDefault’ and no accessible extension method ‘FirstOrDefault’ accepting a first argument of type ‘PropfindResponse’ could be found (are you missing a using directive or an assembly reference?)

The code for downloading a file inside my class is this (error: FirstOrDefault):

        public async Task<WebDavStreamResponse> Download(string url)
        {
            // Retrieve list of items in 'Test' folder
            var folderFiles = await GetItemsAsyncCloudItem(url);
            // Find first file in 'Test' folder
            var folderFile = folderFiles.FirstOrDefault(f => f.IsCollection == false);

            var tempFileName = Path.GetTempFileName();

            // Download item into a temporary file
            using (var tempFile = File.OpenWrite(tempFileName))
            using (var stream = await _webDavClient.GetProcessedFile(folderFile.Href))
                return await stream.CopyToAsync(tempFile);
        }

I used this function in my class to await the file

        public async Task<PropfindResponse> GetItemsAsyncCloudItem(string file)
        {
            return await _webDavClient.Propfind($"remote.php/dav/files/" + _username + "/" + file);
        }

The library in place responds in generic ‘webdav items’, this can be files and/or sub-folders of the given path. In case the path only contain sub-folders, the property “IsCollection” will always be true for all the items, if there are any files within the collection they will have IsCollection = false.

The error you are referring to is probably that you are missing out on using System.Linq;, you need that reference.

You are disposing the streams in place, one for the filestream and one for downloading it in-memory. I do not recommend disposing the HttpClient itself.

I don’t know if you can directly download the folder as a .zip file (or .rar), probably not, you can always test it out.

So what you basically mean is that every sub-folder in my folder (ex. main folder where everything is located) will trigger IsCollection = true ? So I thought maybe I could tell the code the home location of all my sub-folders and check for IsCollection = true and download the required sub-folder according to its name. Or will it just download the sub-folder’s contents as you mentioned?

The problem is, I have been using Linq and checked the project’s references and, as it turns out, System.Linq.dll is checked. Is there any way to fix that error or do you want me to take a screenshot of references?

This means I just need to set the stream variable for downloading the files to NULL or just somehow reset it?

I’ll give it a try.

Try this… did not run it, but does not give any compile errors.

  public async Task Download(string url)
        {
            // Retrieve list of items in 'Test' folder
            var folderFiles = await GetItemsAsyncCloudItem(url);
            // Find first file in 'Test' folder
            var folderFile = folderFiles.Resources.FirstOrDefault(f => f.IsCollection == false);

            var tempFileName = Path.GetTempFileName();

            // Download item into a temporary file
            using (var tempFile = File.OpenWrite(tempFileName))
            using (var stream = await _webDavClient.GetProcessedFile(folderFile.Uri))
                await stream.Stream.CopyToAsync(tempFile);
        }

Note, I modified it to resources, checked also WebDavStreamResponse, it does not have any CopyToAsync.

Also, personally use this library: GitHub - skazantsev/WebDavClient: Asynchronous cross-platform WebDAV client for .NET Core

Yes, I used this and FirstOrDefault function finally gives no errors and seems to be working. But there’s the other problem I’ve been talking about - disposing. You see, I still get the error.

WebDavStreamResponse’: type used in a using statement must be implicitly convertible to ‘System.IDisposable’.

Do you think changing the library to the one you just suggested me might do the trick?

Any suggestions, please? I’d fix it myself but I have never encountered error like this.

Personally I’d switch to the other library I suggested.

Yeah, it works… Thank you.

It is trying to download to temporary file in Temp folder, but somehow the 2,6GB file is downloaded immediately and if I check the file’s size, I have 0B… I think there’s problem somewhere… Is it because I am trying to download a folder instead of a file?

There are a few factors to account for besides if downloading a folder will work or not. Your server / connection should not time-out for example.

Try it first on a file before figuring out if this even works on a folder…