目录

1.环境准备
2.安装SDK
3.初始化client
4.查看Bucket列表
5.查看文件列表
6.文件管理&模拟目录结构
7.文件元信息

Quick Start

阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。本文基于node.js使用阿里云提供的SDK接口将海量数据移入或移出阿里云OSS。

OSS提供多种语言的 API/SDK 包,方便开发人员快速进行二次开发。以下是在Node.js环境中快速使用OSS服务的具体步骤:


环境准备

(1)在使用阿里云 OSS 服务之前,请确保您已经注册了阿里云账号并完成实名认证。使用主账号登录阿里云管理控制台,将鼠标置于页面右上方的账号图标,然后单击accesskeys,创建AccessKeyId和AccessKeySecret。由于云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践。如果部署在服务端可以使用RAM子账号或STS来进行API访问或日常运维管控操作,如果部署在客户端请使用STS方式来进行API访问。

(2)单击对象存储OSS,打开OSS产品详情页面,在OSS产品详情页,单击立即开通,开通服务后,在OSS 产品详情页面单击管理控制台直接进入 OSS 管理控制台界面。

(3)创建存储空间(Bucket)。进入 OSS 管理控制台界面。如果目前 Bucket 列表为空,单击左侧存储空间列表中的新建 Bucket;若已创建过 Bucket,则单击左侧存储空间列表中的新增按钮+,或者单击页面右上方的新建 Bucket 按钮,打开新建 Bucket 对话框(如下图)。接着在此Bucket的文件管理栏目下创建一个文件。

创建Bucket是为了后期使用SDK开发时查看Bucket以及传入文件到此次创建的Bucket中。


安装 SDK

使用Node.js,其中Node.js >= 8.0.0 如果需要在 Node.js < 8 的环境中使用,请使用 ali-oss 4.x版本。
使用npm安装SDK开发包(如下图)。

npm install ali-oss

初始化 Client

  1. region 指申请 OSS 服务时的区域,完整区域列表可在OSS 服务节点查看
  2. accessKeyId 和 accessKeySecret 可在用户信息管理中创建或获取
// app.js
let OSS = require("ali-oss");let client = new OSS({region: "<Your region>",accessKeyId: "<Your AccessKeyId>",accessKeySecret: "<Your AccessKeySecret>"
});

其中’your region’是指在申请OSS服务时的区域,例如申请的是华东1(杭州),region为oss-cn-hangzhou,完整的区域列表可以在OSS服务节点查看。和即在环境安装中创建的AccessKeyId和AccessKeySecret。


查看 Bucket 列表

在app.js末尾添加如下内容,使用listBuckets接口查看Bucket列表:

// app.js
async function listBuckets() {try {let result = await client.listBuckets();console.log("查看Bucket列表");console.log(result);} catch (err) {console.log(err);}
}
listBuckets();// 控制台打印
// 查看Bucket列表
{ buckets:[ { name: 'mvb-demo',region: 'oss-cn-shanghai',creationDate: '2019-03-16T03:18:40.000Z',StorageClass: 'Standard' } ],owner: { id: '1310495523924984', displayName: '1310495523924984' },isTruncated: false,nextMarker: null,res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 03:20:03 GMT','content-type': 'application/xml','content-length': '595',connection: 'keep-alive','x-oss-request-id': '5C8C6B638DA7CAFD2BA82A37','x-oss-server-time': '55' },size: 595,aborted: false,rt: 104,keepAliveSocket: false,data:<Buffer 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 46 2d 38 22 3f 3e 0a 3c 4c 69 73 74 41 6c 6c 4d 79 42 ... >,requestUrls: [ 'http://oss-cn-shanghai.aliyuncs.com/' ],timing: null,remoteAddress: '106.14.228.198',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 } }

其中AliyunOSS即之前创建的Bucket。


查看文件列表

修改app.js,使用list接口查看文件列表:

client.useBucket("Your bucket name");
async function list() {try {let result = await client.list({"max-keys": 5});console.log(result);} catch (err) {console.log(err);}
}
list();

其中’Your bucket name’即之前创建的文件,运行并查看结果node app.js

控制台打印 , 查看文件列表

{ res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 03:27:06 GMT','content-type': 'application/xml','content-length': '226',connection: 'keep-alive','x-oss-request-id': '5C8C6D0AF1C42EA0B7AE2124','x-oss-server-time': '14' },size: 226,aborted: false,rt: 59,keepAliveSocket: false,data:<Buffer 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 46 2d 38 22 3f 3e 0a 3c 4c 69 73 74 42 75 63 6b 65 74 ... >,requestUrls:[ 'http://mvb-demo.oss-cn-shanghai.aliyuncs.com/?max-keys=5' ],timing: null,remoteAddress: '106.14.228.182',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 },objects: undefined,prefixes: null,nextMarker: null,isTruncated: false }

文件管理&模拟目录结构

每个存储空间(Bucket)可以设置多个不同类型的文件对象,例如图片文件对象,文档文件对象等等,依次在对应的文件对象中存放相应的文件(图片文件中存入图片,文档文件中存入文档),通过list来列举当前Bucket下的所有文件。想获取特定前缀的文件,如开头为"my-"的文件,可用prefix只列出符合特定前缀的图片,以下代码用于列举当前Bucket下前缀为“my-”的所有文件:

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',//云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,部署在服务端使用RAM子账号或STS,部署在客户端使用STS。accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',// endpoint: '<http://oss-cn-beijing.aliyuncs.com>'
});async function list () {{let result = await client.list({prefix:'my-'});console.log(result);}
}
list();

后台运行结果为:

PS C:\Users\ASUS\Desktop\aliyun> node app.js
{ res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 07:25:24 GMT','content-type': 'application/xml','content-length': '936',connection: 'keep-alive','x-oss-request-id': '5C8CA4E41B658DCC4216F1D8','x-oss-server-time': '17' },size: 936,aborted: false,rt: 124,keepAliveSocket: false,data:<Buffer 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 46 2d 38 22 3f 3e 0a 3c 4c 69 73 74 42 75 63 6b 65 74 ... >,requestUrls: [ 'http://kekede.oss-cn-beijing.aliyuncs.com/?prefix=my-' ],timing: null,remoteAddress: '59.110.185.149',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 },objects:[ { name: 'my-text/',url: 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text/',lastModified: '2019-03-16T07:17:19.000Z',etag: '"D41D8CD98F00B204E9800998ECF8427E"',type: 'Normal',size: 0,storageClass: 'Standard',owner: [Object] },{ name: 'my-text1/',url: 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text1/',lastModified: '2019-03-16T07:17:31.000Z',etag: '"D41D8CD98F00B204E9800998ECF8427E"',type: 'Normal',size: 0,storageClass: 'Standard',owner: [Object] } ],prefixes: null,nextMarker: null,isTruncated: false }

其中my-text与my-text1文件便是带有"my-"前缀的指定文件,可知当我们想搜索带有特定关键字前缀的文件,即可使用。

OSS是基于对象的存储服务,没有目录的概念。存储在一个Bucket中所有文件都是通过文件的key唯一标识,并没有层级的结构。这种结构可以让OSS的存储非常高效,但是用户管理文件时希望能够像传统的文件系统一样把文件分门别类放到 不同的“目录”下面。通过OSS提供的“公共前缀”的功能,也可以很方便地模拟目录结构。

可以通过 Delimiter 和 Prefix 参数的配合实现文件夹功能:
如果把 Prefix 设为某个文件夹名,就可以罗列以此 Prefix 开头的文件,即该文件夹下递归的所有的文件和子文件夹(目录)。文件名在Contents中显示。如果再把 Delimiter 设置为正斜线(/)时,返回值就只罗列该文件夹下的文件和子文件夹(目录),该文件夹下的子文件名(目录)返回在 CommonPrefixes 部分,子文件夹下递归的文件和文件夹不被显示。
现在Bucket中已有如下文件:

my-text/one/one1
my-text/one/one2
my-text1
dididi
review.zip

接下来用调用函数listDir来列举指定目录下的文件和子目录

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function listDir(dir){let result = await client.list({prefix: dir,delimiter: '/'});result.prefixes.forEach(function (subDir) {console.log('SubDir: %s', subDir);});result.objects.forEach(function (obj) {console.log('Object: %s', obj.name); });
}listDir('my-text/');

运行结果为

SubDir: my-text/one/
SubDir: my-text/two/
Object: my-text/

输入以下代码

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function listDir(dir){let result = await client.list({prefix: dir,delimiter: '/'});result.prefixes.forEach(function (subDir) {console.log('SubDir: %s', subDir);});result.objects.forEach(function (obj) {console.log('Object: %s', obj.name); });
}listDir('my-text/');

运行结果为

SubDir: my-text/
SubDir: my-text1/
(node:12796) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'forEach' of undefinedat listDir (C:\Users\ASUS\Desktop\aliyun\app.js:21:18)at process._tickCallback (internal/process/next_tick.js:68:7)
(node:12796) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a
promise which was not handled with .catch(). (rejection id: 1)
(node:12796) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

文件元信息

向OSS上传文件时,除了文件内容,还可以指定文件的一些属性信息,称为“元信息”。 这些信息在上传时与文件一起存储,在下载时与文件一起返回。
文件元信息在上传、下载时均附在HTTP Headers中, 且HTTP协议规定不能包含复杂字符。使用put,putStream和multipartUpload时,都可以通过指定meta参数来指定文件的元信息:

let OSS = require('ali-oss')let client = new OSS({region: '<Your region>',accessKeyId: '<Your AccessKeyId>',accessKeySecret: '<Your AccessKeySecret>',bucket: 'Your bucket name'
});async function put () {try {let result = await client.put('object-name', 'local-file', {meta: {year: 2016,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}put();

输入以下代码

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function put () {try {let result = await client.put('my-text', '1162.jpg', {meta: {year: 2016,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}put();

运行结果如下

{ name: 'my-text',url: 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text',res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 16:36:17 GMT','content-length': '0',connection: 'keep-alive','x-oss-request-id': '5C8D260131333D99F43812DC',etag: '"AFE392E3D901E3C33F1539DD3DA1276F"','x-oss-hash-crc64ecma': '6266394416455372926','content-md5': 'r+OS49kB48M/FTndPaEnbw==','x-oss-server-time': '26' },size: 0,aborted: false,rt: 687,keepAliveSocket: false,data: <Buffer >,requestUrls: [ 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text' ],timing: null,remoteAddress: '59.110.185.149',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 } }

通过putMeta接口来更新文件元信息:

let OSS = require('ali-oss')let client = new OSS({region: '<Your region>',accessKeyId: '<Your AccessKeyId>',accessKeySecret: '<Your AccessKeySecret>',bucket: 'Your bucket name'
});async function putMeta () {try {let result = await client.putMeta('object-name', {meta: {year: 2015,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}putMeta();

输入以下代码

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function putMeta () {try {let result = await client.putMeta('my-text', {meta: {year: 2015,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}putMeta();

运行结果如下

{ name: 'my-text',url: 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text',res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 16:36:17 GMT','content-length': '0',connection: 'keep-alive','x-oss-request-id': '5C8D260131333D99F43812DC',etag: '"AFE392E3D901E3C33F1539DD3DA1276F"','x-oss-hash-crc64ecma': '6266394416455372926','content-md5': 'r+OS49kB48M/FTndPaEnbw==','x-oss-server-time': '26' },size: 0,aborted: false,rt: 687,keepAliveSocket: false,data: <Buffer >,requestUrls: [ 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text' ],timing: null,remoteAddress: '59.110.185.149',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 } }
PS C:\Users\ASUS\Desktop\aliyun> node app.js
{ data:{ etag: '"AFE392E3D901E3C33F1539DD3DA1276F"',lastModified: '2019-03-16T16:37:59.000Z' },res:{ status: 200,statusCode: 200,statusMessage: 'OK',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 16:37:59 GMT','content-type': 'application/xml','content-length': '184',connection: 'keep-alive','x-oss-request-id': '5C8D26671B658DD589677FDC',etag: '"AFE392E3D901E3C33F1539DD3DA1276F"','x-oss-server-time': '35' },size: 184,aborted: false,rt: 238,keepAliveSocket: false,data:<Buffer 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 22 31 2e 30 22 20 65 6e 63 6f 64 69 6e 67 3d 22 55 54 46 2d 38 22 3f 3e 0a 3c 43 6f 70 79 4f 62 6a 65 63 74 ... >,requestUrls: [ 'http://kekede.oss-cn-beijing.aliyuncs.com/my-text' ],timing: null,remoteAddress: '59.110.185.149',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 } }

拷贝文件:

使用copy拷贝文件,拷贝分两种情况:
同一个Bucket
同一个region下的两个不同Bucket,此时源Object名字应为’/bucket/object’的形式
另外,拷贝时对文件元信息的处理有两种选择:
如果没有指定meta参数,则与源文件相同,即拷贝源文件的元信息。
如果指定了meta参数,则使用新的元信息覆盖源文件的信息。

let OSS = require('ali-oss')let client = new OSS({region: '<Your region>',accessKeyId: '<Your AccessKeyId>',accessKeySecret: '<Your AccessKeySecret>',bucket: 'Your bucket name'
});async function copy () {try {// 两个Bucket之间拷贝let result = await client.copy('to', '/from-bucket/from');console.log(result);// 拷贝元信息let result = await client.copy('to', 'from');console.log(result);// 覆盖元信息let result = await client.copy('to', 'from', {meta: {year: 2015,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}

输入以下代码

 let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function copy () {try {// 两个Bucket之间拷贝let result = await client.copy('my-text1', '/jiayou1111/jiayoou');console.log(result);// 拷贝元信息let result = await client.copy('my-text1', 'dididi');console.log(result);// 覆盖元信息let result = await client.copy('my-text1', 'dididi', {meta: {year: 2015,people: 'mary'}});console.log(result);} catch (e) {console.log(e);}
}

再观看控制台,操作完成。

通过delete来删除某个文件:

let OSS = require('ali-oss')let client = new OSS({region: '<Your region>',accessKeyId: '<Your AccessKeyId>',accessKeySecret: '<Your AccessKeySecret>',bucket: 'Your bucket name'
});async function delete () {try {let result = yield client.delete('object-name');console.log(result);} catch (e) {console.log(e);}
}delete();

输入代码:

let OSS = require('ali-oss');let client = new OSS({region: 'oss-cn-beijing',accessKeyId: 'LTAImmNI5n0A0b3o',accessKeySecret: 'XMcafmH5G5ViSkspkGQE17oTbUZ5iV',bucket: 'kekede',
});async function remove () {try {let result = yield client.delete('dididi');console.log(result);} catch (e) {console.log(e);}
}remove();

结果如下图

{ res:{ status: 204,statusCode: 204,statusMessage: 'No Content',headers:{ server: 'AliyunOSS',date: 'Sat, 16 Mar 2019 17:20:56 GMT','content-length': '0',connection: 'keep-alive','x-oss-request-id': '5C8D3078591574B0552D183C','x-oss-server-time': '20' },size: 0,aborted: false,rt: 196,keepAliveSocket: false,data: <Buffer >,requestUrls: [ 'http://kekede.oss-cn-beijing.aliyuncs.com/dididi' ],timing: null,remoteAddress: '59.110.185.149',remotePort: 80,socketHandledRequests: 1,socketHandledResponses: 1 } }

因上诉delete报错,所以改用remove,再去操作台观看dididi文件已经被删除,操作完成。

还有众多其他功能需阅读阿里云对象存储OSS开发指南:
阿里云对象存储OSS开发指南
作者:木子可可

基于node.js的阿里云对象存储服务OSS相关推荐

  1. 阿里云对象存储服务OSS前后联调

    阿里云对象存储服务OSS前后联调 1.为什么要引入阿里云对象存储服务(OSS)?有什么好处? 1.1.什么是对象存储OSS 1.2.OSS工作原理 2.阿里云对象存储-普通上传方式 2.1.时序图 2 ...

  2. SpringBoot整合——阿里云对象存储(OSS)

    SpringBoot整合--阿里云对象存储 1 OSS介绍 在开发应用的过程中,我们经常会有用户需要实名认证之后才能访问的需求. 用户认证需要上传证件图片.首页轮播也需要上传图片,因此我们要做文件服务 ...

  3. 阿里云对象存储OSS之通过URL形式进行图片处理

    什么是OSS 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量.安全.低成本.高可靠的云存储服务.它具有与平台无关的RESTful API接口,能够 ...

  4. 五个问答,告诉你阿里云对象存储如何助力钉钉战胜业务洪峰

    "基于OSS在弹性扩容.跨省容灾.多租户管理以及传输加速方面的基础能力,钉钉在此次战役过程中,实现了一键切换写入区域,拆分业务到多个区域的功能,同时钉钉在跨区域的图片处理.文档预览的并发处理 ...

  5. 阿里云对象存储OSS竟如此简单

    1.1:什么是阿里云的OSS 阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量.安全.低成本.高可靠的云存储服务.您可以通过本文档提供的简单的RE ...

  6. C# 阿里云对象存储OSS创建、删除、上传代码实现

    一.开始接入 1.Nuget安装Aliyun.OSS.SDK: 2.代码实现: /// <summary> /// 阿里云对象存储服务 /// </summary> publi ...

  7. 如何结合PICgo,Typora以及阿里云对象存储OSS搭建自己图床写博客

    如何利用阿里云对象存储OSS搭建自己图床写博客 1.购买阿里云 购买链接 登录阿里云–>控制台–>对象存储OSS–购买 购买的时候可以选择按月付费一月一元的,也可以年费9元的,40GB作为 ...

  8. 阿里云对象存储OSS与文件存储NAS的区别

    一.简介 应用场景:选择一款存储产品,面向文档数据的存取,不会涉及到数据处理. 产品选型主要从OSS和NAS中选择一款,满足文档存储的需求. 二.NAS优缺点 NAS 是一种采用直接与网络介质相连的特 ...

  9. 使用阿里云对象存储oos遇到跨域访问的问题

    使用阿里云对象存储oos遇到跨域访问的问题,因为第一次使用云存储,初级码渣查了好久文档,终于找到了解决方法. 大概就说了这么多,我的操作是来到oos概览一栏 ,找到跨域访问 做了一个最简单的配置,这样 ...

  10. 阿里云对象存储以及api

    阿里云对象存储 简介 对象存储提供了基于分布式系统之上的对象形式的数据存储服务,并且可以通过 RESTful API 数 据读写接口及丰富的SDK接口进行数据的访问 特点 a)非结构存储 对象存储适用 ...

最新文章

  1. pca主成分分析结果解释_SKLEARN中的PCA(Principal Component Analysis)主成分分析法
  2. StreamSets数据操作平台(数据移动及数据清洗强大工具)-第二篇
  3. eclipse代码补全
  4. opencv-原图基础上添加指定颜色
  5. python怎样导入scrapy_(Python)在导入的模块scrapy中找不到任何项目
  6. 计算机建筑材料考试试题,建筑材料试题(建筑材料期中试题及)
  7. 关于排序算法思想总结,你该了解这些
  8. HDU-2063-过山车(最大匹配)
  9. create-react-app 开发环境编译太慢的解决方案
  10. 过程FMEA:失效模式/失效起因的理论+实例
  11. imx6ul pinctrl 驱动浅析
  12. SQL Server 2014如何导出数据库
  13. 01单片机——基础知识
  14. 怎么增加LINUX虚拟机的运行内存,Mac虚拟机内存怎么分配?虚拟机内存不足解决办法...
  15. stm32串口通信以及C语言程序里的内存分配
  16. 【黑马旅游网】项目完结+未完成功能实现+个人总结+bug记录
  17. [bx]和loop指令
  18. linux服务篇-Xinetd服务
  19. saltstack grain pillar
  20. R语言使用quantmod包的getSymbols函数从指定金融数据源获取指定时间段的股票数据、从雅虎金融读取著名的苹果公司的全部股票数据

热门文章

  1. 数据分析--PEG策略(选股)
  2. 51单片机外设LCD12864显示字符串
  3. mysql with,mysql+with
  4. Android应用市场应用转让申请流程
  5. selenium实现12306全自动购票
  6. 【项目管理】投资回报率 ROI(Return on Investment)
  7. 计算机组成原理实验 实验四:多周期CPU实验要求(源代码全)
  8. 【实现操作系统 02】FAT12 文件系统(摆脱术语用实际例子介绍)
  9. uva1391-Astronauts
  10. mongodb数据库