Giter Club home page Giter Club logo

webdavclient's Introduction

WebDAV .NET client Build status

Asynchronous cross-platform WebDAV client for .NET Core and other runtimes. It aims to have a full support of RFC4918.

Installation

Install WebDav.Client via NuGet.

Install-Package WebDav.Client

Supported platforms

  • .NET Core 1.0+
  • .NET Framework 4.5+
  • Mono
  • Xamarin
  • UWP

For more information see .NET Standard.

Usage notes

WebDavClient uses HttpClient under the hood that is why it is a good practice to share a single instance for the lifetime of the application.

If you use a dependency injection container to manage dependencies it is a good practice to register WebDavClient as a singleton.

It's also possible to instantiate WebDavClient with a pre-configured instance of HttpClient.

When using GetRawFile / GetProcessedFile don't forget to dispose the response.

Usage examples

Basic usage

class Example
{
    public static IWebDavClient _client = new WebDavClient();

    public void MakeCalls()
    {
        var result = await _client.Propfind("http://mywebdav/1.txt");
        if (result.IsSuccessful)
            // continue ...
        else
            // handle an error
    }
}

Using BaseAddress

var clientParams = new WebDavClientParams { BaseAddress = new Uri("http://mywebdav/") };
using (var client = new WebDavClient(clientParams))
{
    await client.Propfind("1.txt");
}

Operations with files and directories (resources & collections)

var clientParams = new WebDavClientParams { BaseAddress = new Uri("http://mywebdav/") };
using (var client = new WebDavClient(clientParams))
{
    await client.Mkcol("mydir"); // create a directory

    await client.Copy("source.txt", "dest.txt"); // copy a file

    await client.Move("source.txt", "dest.txt"); // move a file

    await client.Delete("file.txt", "dest.txt"); // delete a file

    using (var response = await client.GetRawFile("file.txt")) // get a file without processing from the server
    {
        // use response.Stream
    }

    using (var response = await client.GetProcessedFile("file.txt")) // get a file that can be processed by the server
    {
        // use response.Stream
    }

    await client.PutFile("file.xml", File.OpenRead("file.xml")); // upload a resource
}

Authentication using an access token

var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = 
    new AuthenticationHeaderValue("Bearer", accessToken);
var client = new WebDavClient(httpClient);

Authentication using NetworkCredential

var clientParams = new WebDavClientParams
{
    BaseAddress = new Uri("http://mywebdav/"),
    Credentials = new NetworkCredential("user", "12345")
};
var client = new WebDavClient(clientParams);

PROPFIND example

// list files & subdirectories in 'mydir'
var result = await _client.Propfind("http://mywebdav/mydir");
if (result.IsSuccessful)
{
    foreach (var res in result.Resources)
    {
        Trace.WriteLine("Name: " + res.DisplayName);
        Trace.WriteLine("Is directory: " + res.IsCollection);
        // etc.
    }
}

PROPFIND with custom properties

var propfindParams = new PropfindParameters
{
    Namespaces = new [] { new NamespaceAttr("myns", "https://example.com/") },
    CustomProperties = new [] { XName.Get("myprop", "https://example.com/") }
};
var result = await client.Propfind("http://mywebdav/mydir", propfindParams);

Custom headers

var propfindParams = new PropfindParameters
{
    Headers = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("User-Agent", "Not a browser")
    }
};
var result = await _client.Propfind("http://mywebdav/1.txt", propfindParams);

Content-Range or other content headers

// Content headers need to be set directly on HttpContent instance.
var content = new StreamContent(File.OpenRead("test.txt"));
content.Headers.ContentRange = new ContentRangeHeaderValue(0, 2);
var result = await _client.PutFile("http://mywebdav/1.txt", content);

Synchronous API

  // will block the current thread, so use it cautiously
  var result = _client.Propfind("1.txt").Result;

License

WebDavClient is licensed under the MIT License. See LICENSE.txt for more details.

webdavclient's People

Contributors

gregfer avatar ngbrown avatar phobeus avatar skazantsev avatar usselite avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webdavclient's Issues

MSAL claims based authentication not supported

In the web client params, we should be able to pass an AuthenticationHeaderValue to support MSAL, for example the following from the Microsoft MSAL tutorial

            httpClient.DefaultRequestHeaders.Authorization =
                new AuthenticationHeaderValue(Constants.BearerAuthorizationScheme,
                                              accessToken);

Currently this Web DAV Client does not support Microsoft sharepoint since I can't pass the needed access token as part of the header. I might add this in myself if it would be desired.

Using PROPFIND with custom properties (owncloud / nextcloud)

Hey,
i couldn't find a documentation so: Am i doing something wrong or is there a bug?
Im trying to connect to my nextcloud webdav and get some Proeprties:

var param = new PropfindParameters();
param.Namespaces = new List<NamespaceAttr>()
{
   new NamespaceAttr("oc", "http://owncloud.org/ns"),
   new NamespaceAttr("nc", "http://nextcloud.org/ns")
};
param.CustomProperties = new List<XName>()
{
   XName.Get("fileid", "oc:"),
   XName.Get("size", "oc:"),
   XName.Get("owner-display-name", "oc:"),
   XName.Get("mount-type", "nc:"),
};
param.ApplyTo = ApplyTo.Propfind.ResourceAndAncestors;
var result = await _client.Propfind("remote.php/webdav/", param);

The Result ist valid and i get all my Resources, but without any CustomProperties.
But i know these Properties exist, because using curl i get all my CustomProperties

Change ContentType of Request

var requestParams = new RequestParameters { Headers = headers, Content = requestBody };

It would be nice if the ContentType of the RequestParameters-object could be changed from outside WebDavClient class. By default, it is set to "text/plain; charset=utf-8". For example, right now I would like it to be "application/xml; charset=utf-8".

Using PROPPATCH with custom Properties (Nextcloud/owncloud)

Hi.

I could not find documentation to PROPPATCH and looked up your tests to determine how to place custom properties into the propfind Dictionary with a certain schema.

Here is the code I am using:

var _space = "http://example.com";
var _spaceNs = "{" + _space + "}";
// Construct properties
var propDict = new Dictionary<XName, string>
{
    { _spaceNs + "uploader", "chrakker" },
    { _spaceNs + "vertragstyp", item.Get_Property("Type") },
    { _spaceNs + "loeschdatum", item.Get_Property("ReminderDate02") }
};
// Construct Namespaces
var ns = new[]
{
    new NamespaceAttr("oc", "http://owncloud.org/ns"),
    new NamespaceAttr("nc", "http://nextcloud.org/ns"),
    new NamespaceAttr("te", _space)
};
// Construct the parameters
var propParam = new ProppatchParameters {
PropertiesToSet = propDict,
Namespaces = ns
};

// Call the Response
var response = _client.Proppatch(ncPath, propParam).Result;

I expect something like this:

<?xml version=""1.0"" encoding=""utf-8""?>
<D:propertyupdate xmlns:D=""DAV:"" xmlns:te=""http://example.com/"" xmlns:oc=""http://owncloud.org/ns"" xmlns:nc=""http://nextcloud.org/ns"">
    <D:set>
        <D:prop>
            <te:uploader>chrakker</X:prop1>
            <te:vertragstyp>XYZ</X:prop1>
            <te:loeschdatum>01012044</X:prop1>
        </D:prop>
    </D:set>
</D:propertyupdate>;

Sadly, it only takes the last Property from the Dict (here "loeschdatum") and sets it, not the other Properties, disregarding the length of the Dictionary completely.

Can you help me out there?

Infinite blocking GetRawFile(...).Result on SECOND calls

Since I upgraded to version 2.5.0, in my program I am using synchronous IO (since I am working in a Windows Form background worker)

Sample code:

var retRemoteGetTask1 = client.GetRawFile(filename1);
retRemoteGetTask1.Wait(); // Works !
var retRemoteResult1 = retRemoteGetTask1.Result; // retRemoteResult1 is fully filled

var retRemoteGetTask2 = client.GetRawFile(filename2);
retRemoteGetTask2.Wait(); // Infinite wait unless I break the debugger and "quick watch the retRemoteGetTask2 variable) !
//Quick Watching retRemoteGetTask2 : { Id = 41, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}" }
var retRemoteResult2 = retRemoteGetTask2.Result; // NEVER Reaching this line

Java.Net.ProtocolException when using AndroidClientHandler: PROPFIND (and others) unsupported

I am using this library in my multi-platform Xamarin app and attempt to use the native HttpClientHandler on each platform (Windows -> HttpClientHandler, iOS -> NSUrlSessionHandler, Android -> AndroidClientHandler).

In the case of Android:

var httpHandler = new AndroidClientHandler() { AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip };
httpHandler.Credentials = new NetworkCredential(credentials.Username, credentials.Password);
var client = new WebDavClient(new HttpClient(httpHandler, true) { BaseAddress = new Uri(credentials.URL) });

Unfortunately, this causes the following exception when using the WebDavClient:
Java.Net.ProtocolException: Expected one of [OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PATCH] but was PROPFIND

A few possible solutions/workarounds are mentioned here: https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch (X-HTTP-Method-Override, Reflection, ...)

I understand that this is not a bug in your library, but maybe you are interested in adding a workaround anyways...

Progress monitoring with GetRawFile()

Hi, I am trying to use this nice client to download a large data file (>2GB) and would like to monitor the progress and download speed.

Is there any build-in API for doing so? Otherwise I guess I will need to read the stream returned by GetRawFile(), something like

using (var response = await client.GetRawFile("data.mp4"))
{
    using (fileStream = new FileStream("data.mp4", FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
    {
        var totalRead = 0L;
        var totalReads = 0L;
        var buffer = new byte[8192];
        var isMoreToRead = true;

        do
        {
            var read = await response.Stream.ReadAsync(buffer, 0, buffer.Length);
            if (read == 0)
            {
                isMoreToRead = false;
            }
            else
            {
                await fileStream.WriteAsync(buffer, 0, read);

                totalRead += read;
                totalReads += 1;

                if (totalReads % 2000 == 0)
                {
                    Console.WriteLine(string.Format("total bytes downloaded so far: {0:n0}", totalRead));
                }
            }
        }
        while (isMoreToRead);
    }
}

Your help is much appreciated.

Download a file locally.

Hello,

I'm trying to download a file locally using WebDAC.Client. The file is being created but it is empty. Any ideas how to solve this?

Thanks.

create files

How do I create a file in a directory in asp.net core

Propfind not allowing empty path

Running Propfind with an empty path throws an exception. However, this should be allowed as the BaseAddress may contain a URI that is entirely valid without having to add anything to it.

This is easily circumvented by creating your own empty Uri and giving it to Propfind, but still.

digest authentication

Hi, I have a WebDAV server which uses the digest method for authentication.

This appears a problem for WebDavClient. Any advice on how to change WebDavClientParams to use digest credentials?

The error I got is:

{PROPFIND WebDAV response - StatusCode: 417, Description: Expectation Failed}

Many thanks
Ning

Problem, when using Copy & Move operations for files with whilespaces

It seems that the GetAbsolutePath & CreateUri methods do not encode the urls, such as using "%20" for whitespace and so on...

To reproduce the issue, just use Copy or Move method with file(s) that contain whitespaces in filename.
exp :
Move([AbsolutePath] + File 1.txt, [AbsolutePath2] + File 1.txt)
Or :
Move([AbsolutePath] + File%201.txt, [AbsolutePath2] + File%201.txt)

Getting same result.

WebDAV access behind a proxy

We want to upload WebDAV files using this .NET API. However, in order to connect to our WebDAV server, we are required to use a proxy (with authentication). Could this library work behind a proxy?

Thank you in advance

Error 403 in PutFile and GetRawFile but no in GetProcessedFile

I'm using https with basic authentication, I can connect and read a file with GetProcessedFile but the methods PutFile and GetRawFile returns allways 403 Forbidden

        // Tls1.2
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
        // Ignore certificate check
        ServicePointManager.ServerCertificateValidationCallback +=
        (se, cert, chain, sslerror) =>
        {
            return true;
        };

        WebDavClientParams clientParams = new WebDavClientParams();
        clientParams.BaseAddress = new Uri(config.host); // HTTPS URI
        clientParams.Credentials = new NetworkCredential(config.user, config.pass);
        var client = new WebDavClient(clientParams);

            foreach (string file in Directory.EnumerateFiles(this.localFolder, "*", SearchOption.AllDirectories))
            {
                string dirName = file.Replace(this.localFolder, "");
                dirName = dirName.Replace("\\", "/");
                string dest = config.host + config.remoteFolder + dirName;

                    var response = await client.GetRawFile(config.host + "/test.txt"); ->status code 403
                    var response2 = await client.GetProcessedFile(config.host + "/test.txt"); -> status code 200
                    var response1 = await client.PutFile(dest, File.OpenRead(file)); -> status code 403
         }

I want to upload local files to the server
any idea?

StatusCode: 401

Cannot connect to OwnCloud
WebDAV response - StatusCode: 401, Description: Unauthorized

"utf-8" is not a supported encoding name

WebDAV at Synology DS 215+ (DSM 5.2-5644 Update 1).

WebDavClient.Propfind("file name") throws an exception:

{"The character set provided in ContentType is invalid. Cannot read content as string using an invalid character set."} System.Exception {System.InvalidOperationException}

InnerException {"'"utf-8"' is not a supported encoding name.\r\nParameter name: name"} System.Exception {System.ArgumentException}

StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at WebDav.WebDavClient.d__2.MoveNext()

Connection to owncloud fails

I run a apache webserver, which has an OwnCloud instance running. I also host some docker instances, and one uses WebDavClient to send files to OwnCloud. For this I have a few unit test that test uploading a file and creating directories. When I run this locally from Visual Studio 2017, it makes a connection to my server and all tests are ok.

A short while ago, I ported all my code to .Net Core 2.0. I tried to deploy my site as the docker instance, and while building the code it also runs the test again. And they fail. So, my first thought was that from Docker, the test couldn't connect to my host webserver, or maybe something with https issues (but actually, before going to 2.0 it also worked). I therefor added a manual httpClient call to the same webdav url, with basic authentication. And this tests works.

I monitored the apache logs of owncloud, and what I noticed, that every time my local unit test starts, there is a request with a 407 message, and second a 207 request with my username in it:

31.x.x.x - - [06/Sep/2017:11:23:03 +0200] "PROPFIND /remote.php/webdav/ HTTP/1.1" 401 306 "-" "-"
31.x.x.x - peter [06/Sep/2017:11:23:04 +0200] "PROPFIND /remote.php/webdav/ HTTP/1.1" 207 2021 "-" "-"

But when I run the docker unit test, only the first one occurs. I checked the code, but can't seem to find why and how the 2 calls are made, and why in Docker only the first occurs.

I did find a solution. By added a manual header with the basic authentication to the client parameters, my problem is resolved. But, how does this work? Is this a feature of HttpClient to detect the authentication request and add the credentials? Is it possible to override this behaviour from the code. I did try the PreAuthenticate setting, but it doesn't seem to affect anything.

Support special characters in file and directory names

Trying to create a file named "Córdoba" in a directory named "España" will result in mangled (i.e. URL-encoded) file and directory names.

Please support the full range of applicable UTF 8 characters by transparently URL-decoding the file and directory names returned from API methods.

PROPFIND for one single file and Depth Header

Запрос PROPFIND свойств для одного отдельного файла должен содержать в заголовке "Depth: 0" (а не "Depth: 1", как сейчас), "Depth: 1" обычно используется для запроса свойств каталога.

  • Неправильно в текущей реализации (ошибка StatusCode: 403, Description: Forbidden)
curl -i -X PROPFIND http://example.com/webdav/filename.ext --upload-file - -H "Depth: 1" <<EOF
<?xml version="1.0"?>
<a:propfind xmlns:a="DAV:">
<a:prop><a:resourcetype/></a:prop>
</a:propfind>
EOF
  • Правильно
curl -i -X PROPFIND http://example.com/webdav/filename.ext --upload-file - -H "Depth: 0" <<EOF
<?xml version="1.0"?>
<a:propfind xmlns:a="DAV:">
<a:prop><a:resourcetype/></a:prop>
</a:propfind>
EOF

PutFile of ~700MB file leads to "The I/O operation has been aborted because of either a thread exit or an application request".

As full disclosure: I'm using dotnetcore and the 3.0 preview 6; so this might not be an issue with this library per se.

I'm trying to upload a large file to the webdav but I get hit with an exception:

Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..

The application certainly isn't requesting a cancel; at least not from my code. And this works for smaller files, as well as the webdav client I've written in Python.

Only "200 - OK" results on Xamarin

NuGet version: 2.3.1
I am having a weird issue using this library in my Xamarin.Android & Xamarin.iOS project. I am connecting with a Nextcloud 15.0.2.0. I am providing correct URL, username but WRONG password.
Now, on iOS & Android I get only "OK" responses however, no matter what methods I call, e.g.:
PROPFIND WebDAV response - StatusCode: 200, Description: OK

In my UWP project, I am getting the expected result:
PROPFIND WebDAV response - StatusCode: 401, Description: Unauthorized

Tried to debug with Fiddler, but for some reason the web traffic didn't show up.

Support custom request methods

I wanted to use this library to implement a CalDAV (which is based on WebDAV) library, but CalDAV requires a REPORT request which is not supported by this. If there was a way to send custom requests I could use this good library instead of using my own (small) implementation of WebDAV.

The DEPTH option "1,noroot" should be added

Hi,

The plugin as I see currently only supports options to fetch properties for resource itself, resource + children and the infinite one.
In a situation where I need to fetch the files tree I want to fetch only children for each call and that can be done with "1,noroot" depth setting.
For clarification, at the moment when I fetch the "Images" folder props I get => Images folder, image1.jpg, image2.jpg etc. I want only the images, not the selected folder.

image

https://docs.microsoft.com/en-us/previous-versions/office/developer/exchange-server-2003/aa142960%28v%3dexchg.65%29

WebDav Service Unavailable with .net core 3.1

Hello,
i'm using your library with an asp.net core 2.2 api. Everything works fine.
now i tried to push the version to .net core 3.1.
Building and running is fine, but the application is not able to connect to the webdav-server.
It says the server would be unavailable (Http Status Code 503)

Do somebody know how to handle this issue? Is there a breaking Change in Http Requests maybe i didnt get?

Greetings,
Glorfinkel

Strange work with DestLockToken in Copy()

Hi, I try to use Copy with DestLockToken (with overwrite option). Firstly, I create lock token for destination file (via Lock, that creates new empty locked file) and then specify this in DestLockToken, call Copy(), then obtain Precondition Failed 412. It is strange, because I have actual lock token for file. Same trick works for PutFile(), where I lock rewritable file (even it is does not exists) and use this lock token for writing data. My WebDAV server bytemark/webdav logs that header "If:" was received but resource not found.
.net core 3.1
Thank you for attention

Listing files isn't giving names

I'm using the example code

var result = await _client.Propfind(baseAddress);
            if (result.IsSuccessful)
            {
                
                foreach (var res in result.Resources)
                {
                    Trace.WriteLine("Name: " + res.DisplayName);
                    Trace.WriteLine("Is directory: " + res.IsCollection);
                    Trace.WriteLine("Content Type: " + res.ContentType);
                    Trace.WriteLine("Content Length: " + res.ContentLength);
                }
            }

It's showing me the content type, content length also telling about if it's a directory. But I can't get name from there. Name is empty. Why is that?

Please upload a strong named version to NuGet

Thanks for creating this well-designed WebDAV client library. I've used it to good effect and so far without any problems whatsoever.

For the strong named version of one of my NuGet packages I need to reference WebDavClient as a signed assembly. I'd much prefer to reference a NuGet package of WebDavClient signed by its author to including a re-signed version of the library in my own packages.

UseDefaultCredentials not being set to false when Credentials supplied

issue is with ConfigureHttpClient method in WebDavClient.cs.

Consider the following code:

 _clientParams = new WebDavClientParams()
            {
                BaseAddress = new Uri(url),
                Credentials = new NetworkCredential() { UserName = "test", Password = "test" },
                UseDefaultCredentials = false
            };
using (var webDavClient = new WebDavClient(_clientParams))
            {
                var result = await webDavClient.Propfind(_fileToGet);
                if (result.IsSuccessful){}
                // continue ...
                else{}
                // handle an error

                return "";
            }

Even though i'm explicitly setting credentials, i must also set UseDefaultCredentials to false for it to auth correctly. If you update this code to remove UseDefaultCredentials=false, you'll get a 403 when trying to .Propfind

I have a branch with fix already, or make the following change to ConfigureHttpClient:

if (@params.Credentials != null)
            {
                httpHandler.Credentials = @params.Credentials;
                httpHandler.UseDefaultCredentials = false;
            }

This is also likely the cause of the other issue reported.

PutFile creates an empty file

I'm sharing this to hopefully help others scratching their heads with a similar issue.
I was changing code originally using HttpWebRequest, in order to tidy up & make use of your library instead.

In my example I have 2 MemoryStreams, stream1 has dummy text as used in your example code, and stream 2 contains some serialized xml.

var stream1 = new MemoryStream(Encoding.UTF8.GetBytes("<content/>"));

var stream2 = new MemoryStream();
var streamWriter = new StreamWriter(stream, System.Text.Encoding.UTF8)
serializer.Serialize(streamWriter, sampleXml);
 
var resPutFile1 = await client.PutFile(exportFile1, stream1);
var resPutFile2 = await client.PutFile(exportFile2, stream2);

Stream 1 was succesfully written to exportFile1.
Stream 2 wasn't written to exportFile2 - the file itself was created but with no content.

The issue (fixed) was with the memory stream position - it needed to be set to 0 before calling PutFile, in order to read the whole stream and write it out to the file.

stream2.Position = 0;
var resPutFile2 = await client.PutFile(exportFile2, stream2);

I thought thought I'd flag this since HttpWebRequest happily seems to take care of that itself, and I never needed to specify the position, it just reads the stream from the beginning.

When uploading large files which takes more then 100 seconds to complete, I get Exception

When using PutFile(. . . ) and the upload takes more then 100 seconds to upload, I get this exception

InnerException = {System.ObjectDisposedException: Cannot access a closed file.
   at System.IO.__Error.FileNotOpen()
   at System.IO.FileStream.get_Position()
   at StackSharing.Lib.StackClient.UploadFile(UploadStatus status, OnlineItem folder, String filePath)

It's probably because when creating a HttpClient, there is no possible override from the default timeout from 100 seconds:

https://github.com/skazantsev/WebDavClient/blob/master/src/WebDav.Client/WebDavClient.cs#L711

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.