Git Product home page Git Product logo

cos-nodejs-sdk-v5's Introduction

cos-nodejs-sdk-v5

腾讯云 COS Nodejs SDK(XML API

releases and changelog

install

npm 地址

npm i cos-nodejs-sdk-v5 --save

demo

// 引入模块
var COS = require('cos-nodejs-sdk-v5');
// 创建实例
var cos = new COS({
  SecretId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  SecretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
});

// 存储桶名称,由bucketname-appid 组成,appid必须填入,可以在COS控制台查看存储桶名称。 https://console.cloud.tencent.com/cos5/bucket
var Bucket = 'test-1250000000';
// 存储桶Region可以在COS控制台指定存储桶的概览页查看 https://console.cloud.tencent.com/cos5/bucket/
// 关于地域的详情见 https://cloud.tencent.com/document/product/436/6224
var Region = 'ap-guangzhou';

// 高级上传
cos.uploadFile(
  {
    Bucket: Bucket,
    Region: Region,
    Key: '1.zip',
    FilePath: './1.zip', // 本地文件地址,需自行替换
    SliceSize: 1024 * 1024 * 5, // 触发分块上传的阈值,超过5MB使用分块上传,非必须
  },
  function (err, data) {
    console.log(err, data);
  }
);

说明文档

使用例子

快速入门

接口文档

cos-nodejs-sdk-v5's People

Contributors

0nese7en avatar annexwu avatar carsonxu avatar konakonall avatar livehigh avatar medz avatar misterapp avatar orangemi avatar tinnazhang avatar tomleader avatar whidy avatar wonder233 avatar yugasun 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  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

cos-nodejs-sdk-v5's Issues

putObject percent 等于1了,却没有触发回调

cos.putObject({
    ContentLength: contentLength,
    Bucket,
    Region,
    Key: filename,
    Body: body, // stream
    onProgress(progressData) {
      console.log(progressData);
    },
  },
  function(err, data) {
    console.log(err || data)
    if (err) {
      console.log('callback', err);
      reject(err);
    }
    resolve(data);
  }
);

image

getService方法 返回的Bucket时间格式有误

随便创建一个Bucket 接口返回的时间是: 2017-08-11T09:26:52Z

UTC时间格式?

解析一下时间

结果是: 2017-08-11 17:26:52

昨天下午创建的bucket 拿到的时间转换一下后是 凌晨的...

你们的Bucket时间拿错了 真的

Object 返回的时间是正确的!

使用`forEach`对文件进行循环上传,但数组中的第二个和第三个文件上传总是出错

我使用fs.readdirSync读取文件夹里的文件,然后用forEach对文件进行循环上传,但每次第二个和第三个文件总是会报错 Code: 'MalformedXML', Message: 'The XML you provided was not well-formed or did not validate against our published schema.',

下面是我的代码:

require('dotenv').config({
	path: '../.env'
});

var COS = require('cos-nodejs-sdk-v5');
var fs = require('fs');

var cos = new COS({
	SecretId: process.env.COS_SECRET_ID,
	SecretKey: process.env.COS_SECRET_KEY,
});

console.log('Angular File Uploading...');

fs.readdirSync('./dist/').forEach(file => {
	cos.sliceUploadFile({
		Bucket: 'test-' + process.env.COS_APPID,
		Region: 'ap-shanghai',
		Key: 'resource/' + file,
		FilePath: './dist/' + file
	}, function(err, data) {
		if(err) {
			console.error(err);
		}
	});
})


下面是报错信息:

{ error: 
   { Code: 'MalformedXML',
     Message: 'The XML you provided was not well-formed or did not validate against our published schema.',
     Resource: '************************************',
     RequestId: '************************************',
     TraceId: '************************************' },
  statusCode: 400,
  headers: 
   { 'content-type': 'application/xml',
     'content-length': '540',
     connection: 'close',
     date: 'Fri, 24 Aug 2018 07:29:41 GMT',
     server: 'tencent-cos',
     'x-cos-request-id': '************************************',
     'x-cos-trace-id': '************************************' } }


不管什么文件只要在读取数组的第二个和第三个,也就是引索是1,2的时候,上传就会报上面的错,其他的位置没问题

关于上传进度

我有一个疑问,我看demo都是从浏览器端上传完整文件到服务器,再从服务器上传到qcloud,这种方式我应该如何控制进度,是否存在代理的方式,之间把上传流转到qcloud而不再本地存储。

能否增加Base64上传支持?

如题,很多时候在node端拿到的其实是文件的base64编码,这样可以摆脱filepath的拘束。COS端有base64的上传接口吗?如果有能否支持?

网络中断错误

D:\visualization-server\node_modules\cos-nodejs-sdk-v5\sdk\base.js:131
var contents = data.ListBucketResult.Contents || [];
^

TypeError: Cannot read property 'Contents' of undefined
at D:\visualization-server\node_modules\cos-nodejs-sdk-v5\sdk\base.js:131:46
at cb (D:\visualization-server\node_modules\cos-nodejs-sdk-v5\sdk\base.js:2073:13)
at Request. (D:\visualization-server\node_modules\cos-nodejs-sdk-v5\sdk\base.js:2119:29)
at Request.emit (events.js:164:20)
at IncomingMessage. (D:\visualization-server\node_modules\request\request.js:1085:12)
at Object.onceWrapper (events.js:254:19)
at IncomingMessage.emit (events.js:164:20)
at endReadableNT (_stream_readable.js:1054:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickDomainCallback (internal/process/next_tick.js:218:9)

网络中断 会出现错误

关于是否可以通过代理文件上传请求直接上传到qcloud

我看了sliceUploadFile和putObject等方法的示例,好像都是从我server读取一个文件/文件流上传到qcloud服务器。我想问下sdk是否提供了代理的方式,让我从server把上传文件请求代理到qcloud服务器,而不需要保存到本地。

没有提供 package.json

按照官网的 sdk 配置步骤,需要执行一次 npm install ,但是并没有 package.json 文件,npm install 并不能成功执行。目前只能通过手动查看引用依赖来安装相应的库,希望补上 package.json

请问为什么一直报403错误

使用该sdk ,sliceUploadFile 上传图片 ,一直报403错误,求解,东西都没有错

{"error":{"Code":"AccessDenied","Message":"Access Denied.","Resource":"zp-125143.cos.ap-sh**ai.myqcloud.com/upload/1526661248697.png","RequestId":"NWFmZjAwNzlfZGFhMDY4NjRfODZkNl83N2I3YQ==","TraceId":"OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTQyYWVlY2QwZTk2MDVmZDQ3MmI2Y2I4ZmI5ZmM4ODFjZmJjODk2ZGRhYzY5ODkwOWQ1NThkZTFhOWQyNTY3MjM="},"statusCode":403,"headers":{"content-type":"application/xml","content-length":"476","connection":"close","date":"Fri, 18 May 2018 16:34:01 GMT","server":"tencent-cos","x-cos-request-id":"NWFmZjAwNzlfZGFhMDY4NjRfODZkNl83N2I3YQ==","x-cos-trace-id":"OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTQyYWVlY2QwZTk2MDVmZDQ3MmI2Y2I4ZmI5ZmM4ODFjZmJjODk2ZGRhYzY5ODkwOWQ1NThkZTFhOWQyNTY3MjM="}

分片上传提示 400 InvalidArgument

近期由于华北园区上线新的 MultipartComplete 接口,导致分片上传方法返回如下错误:

{
    error: {
        Code: 'InvalidArgument',
        Message: 'Invalid Argument',
        xxx: xxx
    }
}

如遇到,请尝试更新到最新版本代码。

ETag 和 签名算法的问题

  1. 很无语,ETag,到底是什么算法?怎么调接口调着调着就从sha1变成md5了。。。。。如果是算法不确定文档里写清楚啊。然而sdk里的逻辑:
计算完分块的 ETag 值,以及获取到上传成功的文件分块的 ETag ,然后合并两者,更新需要上传的分块
  1. x-cos-content-sha1,貌似不校验?

  2. 签名算法urlencode更蛋疼。golang的实现空格转义为+,js的实现转义为%20;golang的实现/转义为%2F,js的实现转义为%2f,其他还有什么坑还不知道,难道我要把相关库重新实现一遍么?

putObject在第10000次后失效

这个问题让我们服务炸了三天

Current:

        if (queue.length > cos.options.UploadQueueSize) {
            queue.splice(0, queue.length - cos.options.UploadQueueSize);
        }

Fix:

        if (queue.length > cos.options.UploadQueueSize) {
            const delta = queue.length - cos.options.UploadQueueSize;
            queue.splice(0, delta);
            nextUploadIndex -= delta;
        }

TypeError: params.outputStream.on is not a function

2018-09-26 08:34 +08:00: TypeError: params.outputStream.on is not a function
at COS._submitRequest (/wiz/app/wizserver.20180925.1736/node_modules/cos-nodejs-sdk-v5/sdk/base.js:2268:29)
at /wiz/app/wizserver.20180925.1736/node_modules/cos-nodejs-sdk-v5/sdk/base.js:2061:24

这个是什么错误?

Error: socket hang up

使用putObject上传一个音频文件,报这样的错误。

{ error:
   { Error: socket hang up
       at createHangUpError (_http_client.js:344:15)
       at Socket.socketOnEnd (_http_client.js:436:23)
       at emitNone (events.js:110:20)
       at Socket.emit (events.js:207:7)
       at endReadableNT (_stream_readable.js:1047:12)
       at _combinedTickCallback (internal/process/next_tick.js:102:11)
       at process._tickCallback (internal/process/next_tick.js:161:9) code: 'ECONNRESET' } }

这是上传文件的代码:

const saveAudio = (ctx, audio, id)=>{
    return new Promise((resolve, reject)=>{
        const { name, mimetype } = audio
        if(mimetype.indexOf('audio')==-1){
            resolve({
                code: 1,
                msg: '文件格式错误'
            })
        }
        let location = `audios/${name}`;
        let param = Object.assign({},baseParam,{
            Key: location,
            Body: audio,
            ContentType: 'application/octet-stream',
            ContentLength: ctx.request.length,
            onProgress: function (progressData) {
                console.log(progressData);
            }
        })
        cos.putObject(param,function(err,data){
            if(err){
                console.log(err)
                reject(err)
            }
            resolve({
                name: name,
                src: baseSrc+location
            })
        })
    })
}

param部分

 {
    Bucket: myBucket,
    Region: 'cn-north',
    Key: 'audios/test.mp3',
    Body: audio, // 可写流
    ContentType: 'application/octet-stream',
    ContentLength: ctx.request.length,
    onProgress: function (progressData) {
           console.log(progressData);
    }
}

putObject 中的 Body对象类型,验证逻辑太严格?

一个 Atom下的插件,更新 sdk 到最新版以后,没法上传了。提示:params body format error, Only allow File|Blob|String'

Body 使用 fs.readFileSync(filepath)fs.createReadStream(filepath) 都不行。尝试用 ToString ,别的地方又出错。

测试了一下,在命令行中,可以正常上传,Atom里就废了。 最后定位到这里:

var getFileSize = function (api, params, callback) {
    var size;
    if (util.isBrowser) {
        if (typeof params.Body === 'string') {
            params.Body = new global.Blob([params.Body]);
        }
        if (params.Body instanceof global.File || params.Body instanceof global.Blob) {
            size = params.Body.size;
        } else {
            callback({error: 'params body format error, Only allow File|Blob|String.'});
            return;
        }
    }

请问这是 Bug 还是要用其他方式传递 Body? 其他方式的话,应该是什么呢?新手学习中,很多函数不知道, 找了快一天了,没找到能用的办法。

缺少list对象功能

s3, oss都有通过一个key查询对象的功能,cos没有。这是一个很基础的功能,请考虑增加。

上传文件时ECONNRESET

用demo上传文件时

以下是config

    Bucket: 'tbtest',
    Region: 'cossh'

以下是log

node node_modules/cos-nodejs-sdk-v5/demo/demo.js
1mb.zip create success
{ error:
   { Error: socket hang up
       at createHangUpError (_http_client.js:302:15)
       at Socket.socketOnEnd (_http_client.js:394:23)
       at emitNone (events.js:91:20)
       at Socket.emit (events.js:188:7)
       at endReadableNT (_stream_readable.js:975:12)
       at _combinedTickCallback (internal/process/next_tick.js:80:11)
       at process._tickCallback (internal/process/next_tick.js:104:9) code: 'ECONNRESET' } }

sliceUploadFile 方法上传文件以后,静态网站不能访问

代码如下:

uploadFileList.forEach((item)=>{
    cos.sliceUploadFile({
        Bucket: args.bucket,
        Region: args.region,
        Key: item.key,
        FilePath: item.filePath,
    }, (err, data)=>{
        if (err) {
            console.log(err);
        } else {
            console.log(data);
        }
    });
 });

其中,uploadFileList是一个数组,遍历出的item对象如下

{ 
    key: '/tags/PHP/index.html',
    filePath: '/home/dongdong/Documents/hexo/public/tags/PHP/index.html'
 }

假设静态托管的网址为http://exp.com
上传完成后,访问这个页面(http://exp.com/tags/PHP),会报unexpectedly closed the connection.
但是如果访问http://exp.com/tags/PHP/index.html,就正常,而且我如果手动上传这个文件,就不会出现这种情况,所有的访问都是正常的

文件上传还有太多要改进的地方,求跟进!!!

到目前为止,上传这块儿还欠缺好多要改进的地方额。你现在只是在文件上传成功后 返回一个状态!
具体说下问题:
1、上传的过程中读取不到单个文件上传进度;
2、多文件同时上传可有什么限制?最多同时上传文件个数,以及每个文件上传的进度;
3、Upload Part[支持的块的数量为1到10000,块的大小为1 MB 到5 GB],这里指的是所有文件加一起的块限制吧? 那我同时上传一万多个文件怎么办!
4、暂停上传单个文件呢?暂停所有文件呢?
5、客户端异常退出或者网络断开 再到恢复 之前未上传和正在上传等的进度信息如何获取?

There's still a lot to change ! 頑張って!

希望改写支持Promise

支持Promise 能够回避一些难以调试的错误,同时也能减轻代码横向发展的症状。十分期待,未来对此的支持

sliceUploadFile能否增加支持Buffer

我试着修改task.js的代码第89行

if(Buffer.isBuffer(params.FilePath)){
    size = params.FilePath.size;
}
else{
    size = fs.statSync(params.FilePath).size;
}

但是会报400 Invalid Arguments

SDK更新为啥不能兼容旧的版本,版本号都没意义么,不记得腾讯技术这么渣呀

{ error:
{ Code: 'MalformedXML',
Message: 'The XML you provided was not well-formed or did not validate agai
nst our published schema.',
Resource: 'backup0-1253554307.cos.ap-guangzhou.myqcloud.com/a.txt',
RequestId: 'NWE0MWI5MjdfMTliYjk0MGFfZDI5MV80MTBkM2I=',
TraceId: 'OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2M
TRlY2MzZDhmNmI5MWI1OTI5MWRkM2I1ZDU3ZWE5Y2YzNDYzZTEzY2JlMjU3NDQ0MTAzNGQyNTFiM2NjY
jgzZjgwNGNmNTRjMmM3OWNhZGM=' },
statusCode: 400,
headers:
{ 'content-type': 'application/xml',
'content-length': '531',
connection: 'close',
date: 'Tue, 26 Dec 2017 02:51:19 GMT',
server: 'tencent-cos',
'x-cos-request-id': 'NWE0MWI5MjdfMTliYjk0MGFfZDI5MV80MTBkM2I=',
'x-cos-trace-id': 'OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1
NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTI5MWRkM2I1ZDU3ZWE5Y2YzNDYzZTEzY2JlMjU3NDQ0MTAzNGQy
NTFiM2NjYjgzZjgwNGNmNTRjMmM3OWNhZGM=' } }

建议增加下载为stream的功能

现在是直接保存成文件,并且是下载完成后才会回调。

应该增加下载对象为stream,这样方便把这个stream pipe到http response里面。否则的话,就只能下载到本地临时文件,然后再返回给客户。对于大文件,很容易超时,至少效率有问题。直接返回一个stream就好多了。s3,oss都是可以的

throw new Error('"start" option must be <= "end" option');

"cos-nodejs-sdk-v5": "^2.3.6"

2018-04-09 10:38:12.723 58f05b19 Error: "start" option must be <= "end" option
2018-04-09 10:38:12.723 58f05b19 at new ReadStream (fs.js:1962:13)
2018-04-09 10:38:12.724 58f05b19 at Object.fs.createReadStream (fs.js:1923:10)
2018-04-09 10:38:12.724 58f05b19 at COS.uploadSliceItem (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:486:19)
2018-04-09 10:38:12.724 58f05b19 at /var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:420:25
2018-04-09 10:38:12.724 58f05b19 at replenish (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/async.js:19:13)
2018-04-09 10:38:12.724 58f05b19 at Object.eachLimit (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/async.js:35:7)
2018-04-09 10:38:12.724 58f05b19 at COS.uploadSliceList (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:415:11)
2018-04-09 10:38:12.724 58f05b19 at Array. (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:54:25)
2018-04-09 10:38:12.724 58f05b19 at EventProxy.cos.emit (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/event.js:24:20)
2018-04-09 10:38:12.725 58f05b19 at /var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:95:20
2018-04-09 10:38:12.725 58f05b19 at Array. (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:241:9)
2018-04-09 10:38:12.725 58f05b19 at EventProxy.cos.emit (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/event.js:24:20)
2018-04-09 10:38:12.725 58f05b19 at /var/www/node_modules/cos-nodejs-sdk-v5/sdk/advance.js:261:16
2018-04-09 10:38:12.725 58f05b19 at _callback (/var/www/node_modules/cos-nodejs-sdk-v5/sdk/util.js:295:25)
2018-04-09 10:38:12.725 58f05b19 at /var/www/node_modules/cos-nodejs-sdk-v5/sdk/base.js:1494:20

访问图片

为啥我上传图片后,访问 url 不是显示图片,而是让我下载?

上传完图片后怎样请求图片

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied.</Message>
<Resource>
aodi-1257103690.cos.ap-shanghai.myqcloud.com/AD-16.JPG
</Resource>
<RequestId>NWI1NzYwNmFfZTFhMDY4NjRfMzE1OV9hYjZiY2Y=</RequestId>
<TraceId>
OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTQyYWVlY2QwZTk2MDVmZDQ3MmI2Y2I4ZmI5ZmM4ODFjZmJjODk2ZGRhYzY5ODkwOWQ1NThkZTFhOWQyNTY3MjM=
</TraceId>
</Error>

非标准Error难以调试

现在抛出的错误不是标准Error对象,没有堆栈,难以跟踪debug,建议使用下面的形式
var e=new Error(‘some error’)
e.info = 'other info'
throw e

问题?求解

1、COS.config.setAppInfo(AppId, SecretId, SecretKey, timeout)
v3 nodeSDK之前有上面这接口,这里可不可以用?我用时报错 "....setAppInfo ##undefined"

2、在bucket里面建文件夹,用putObject() 可以上传到bucket的子文件夹里面吗?

3、putObject()返回的ETag是做什么用的?有包含文件信息?MD5 算法校验值可以解密?上传的是图片或视频可以通过指定的 url 预览吗?
以上问题求解啊,谢谢!

node sdk生成的Authorization在js sdk上用不了

node sdk
js const cos = new COS({ SecretId: this.config.SecretId, SecretKey: this.config.SecretKey }) const Authorization = cos.getAuth({ Method: reqData.method, key: '', Expires: 3600 })
js sdk
js var cos = new COS({ getAuthorization: function(options, callback) { callback({ Authorization: res.data.Authorization }) } }) cos.putObject( { Bucket: res.data.Bucket, Region: res.data.Region, Key: Key, Body: Body }, function(err, data) { console.log(err, data) return data } )
wx1 ndm c0 2 jw6cl20

这是什么情况

{ loaded: 20215, total: 10485760, speed: 18511.9, percent: 0 }
{ loaded: 20215, total: 10485760, speed: 0, percent: 0 }
{ error: { Error: socket hang up
at createHangUpError (_http_client.js:312:15)
at TLSSocket.socketOnEnd (_http_client.js:405:23)
at TLSSocket.emit (events.js:187:15)
at endReadableNT (_stream_readable.js:1091:14)
at process._tickCallback (internal/process/next_tick.js:174:19) code: 'ECONNRESET' } }

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.