此demo将通过使用:创建空间、上传文件、获取文件列表、下载文件等API演示如何创建文档空间、上传文档至指定空间等基本的云端文档操作。在此之前,请先理解云文档相关的概念,如“空间”、“文档”、“组织”、repo、container、workspace等。
云文档服务通过调用创建空间、上传文件、获取文件列表、下载文件等API完成文档上传和管理等,满足创建空间、上传文件、获取文件列表、下载文件等需求。
如果没有空间,则需要先创建一个空间;然后在此空间内进行文件操作。

可详见 空间集成示例
创建应用,获取appkey、appsecret;
获取服务调用token;
开通服务,scope授权通过;
以上步骤可参考前置准备
step1:创建空间
云文档有“空间”的概念,用来实现文档的分组。此示例中我们只创建一个空间,作为默认空间。
step2:上传文件
将本地文件上传到云文档中。
step3:获取文件列表
可以查看上传了那些文件。
step4:下载文件
将云文档的文件直接下载下来。
JsonObject json = new JsonObject();
// 空间名称
json.addProperty("name", "测试sdk创建空间222255555");
//空间类型 无限空间
json.addProperty("type","WorkspaceType.UNLIMITED.getCode()");
// 空间描述
json.addProperty("description","自测创建的空间22222111");
// 创建者ID 广联云用户ID 可以为空
json.addProperty("creatorId","6275853124802441678");
//空间的权限类型
json.addProperty("privilege","默认值为0");
String url = "http://apigate.hsifue.cn/gdoc/gws/v4/service/workspaces?access_token="+SERVICE_TOKEN;
res = HttpUtil.sendPost(url, json.toString(), "application/json", "Bearer " + SERVICE_TOKEN);
// workspaceId为 步骤1创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// 上传到指定的父目录id下
String parentFolderFileId = "ec7dc0dab5c44daeb47a224bc73da20d";
String fileName = "textStreaming.dmg";
// 文件大小 需要本地提前计算 单位字节
Long fileLength = 100L;
// 从哪个字节开始 一般为空 表示0
Long position = null;
// 保留字段
String digest = null;
HttpHeaders headers = new HttpHeaders();
headers.setAcceptCharset(Collections.singletonList(Charset.forName("UTF-8")));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpEntity<FileSystemResource> httpEntity = new HttpEntity<>(new FileSystemResource("/Users/sidney/Downloads/YoudaoNote.dmg"), headers);
String url = "http://apigate.hsifue.cn/gdoc/v3/doc/"+workspaceId+"/file/data?parentId="+parentFolderFileId+"&fileName="+fileName+"&size="+fileLength+"&position="+position+"&digest="+digest+"&access_token="+SERVICE_TOKEN;
res = HttpUtil.sendPost(url, httpEntity, "application/json", "Bearer " + SERVICE_TOKEN);
// workspaceId为 步骤1创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// parentFilePath的路径会自动补全 比如 /a/b 其中如果/a/b不存在 服务器会自动创建/a和/a/b两级目录
String parentFilePath = "/";
String fileName = "textStreaming.dmg";
// 文件大小 需要本地提前计算 单位字节
Long fileLength = 100L;
// 从哪个字节开始 一般为空 表示0
Long position = null;
// 保留字段
String digest = null;
HttpHeaders headers = new HttpHeaders();
headers.setAcceptCharset(Collections.singletonList(Charset.forName("UTF-8")));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
HttpEntity<FileSystemResource> httpEntity = new HttpEntity<>(new FileSystemResource("/Users/sidney/Downloads/YoudaoNote.dmg"), headers);
String url = "http://apigate.hsifue.cn/gdoc/v3/doc/"+workspaceId+"/file/data?filePath="+parentFilePath+"&fileName="+fileName
+"&size="+fileLength+"&position="+position+"&digest="+digest+"&access_token="+SERVICE_TOKEN;
res = HttpUtil.sendPost(url, httpEntity, "application/json", "Bearer " + SERVICE_TOKEN);
// workspaceId为 步骤1创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// 获取指定的父目录id下子文件列表
String parentFolderFileId = "ec7dc0dab5c44daeb47a224bc73da20d";
// SERVICE_TOKEN为前置准备 步骤3 中获取的应用token
// Integer pageIndex 第几页
// Integer pageItemCount 每页个数
// orderByType 排序字段 [NAME|TIME]
// order 排序方向 [ASC|DESC]
String url = "http://apigate.hsifue.cn/gdoc/v3/doc/"+workspaceId+"/file/children?fileId="+parentFolderFileId+"&pageIndex="+pageIndex +"&access_token="+SERVICE_TOKEN;
res = HttpUtil.sendGet(url, "Bearer " + SERVICE_TOKEN);
// workspaceId为 步骤1创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
String parentFilePath = "/";
// SERVICE_TOKEN为前置准备 步骤3 中获取的应用token
// Integer pageIndex 第几页
// Integer pageItemCount 每页个数
// orderByType 排序字段 [NAME|TIME]
// order 排序方向 [ASC|DESC]
String url = "http://apigate.hsifue.cn/gdoc/v3/doc/"+workspaceId+"/file/children?filePath="+parentFilePath+"&pageIndex="+pageIndex +"&access_token="+SERVICE_TOKEN;
res = HttpUtil.sendGet(url, "Bearer " + SERVICE_TOKEN);
// workspaceId为 步骤1创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// fileId为 上传成功后服务端返回的GFile.getFileId()
String fileId = "ec7dc0dab5c44daeb47a224bc73da20d"
// 此接口返回的是一个下载签名外链 GSignedFile.signedURL 可直接用于下载
String url = "http://apigate.hsifue.cn/gdoc/v3/doc/"+workspaceId+"/file/signedURL?fileId="
+fileId+"&access_token="+SERVICE_TOKEN;
res = HttpUtil.sendGet(url, "Bearer " + SERVICE_TOKEN);
<!-- 请使用packages.hsifue.cn自动生成的settings.xml文件作作为maven设置 -->
<!-- 地址为http://packages.hsifue.cn/artifactory/maven-Bimface-snapshots/com/glodon/paas/foundation/${artifactId}/ -->
<!-- gdoc -->
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gdoc-java-sdk</artifactId>
<version>1.8.6-SNAPSHOT</version>
</dependency>
<!-- gws -->
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gws-java-sdk</artifactId>
<version>1.2.1-SNAPSHOT</version>
</dependency>
String apiBaseDomain = "http://apigate.hsifue.cn/gdoc/";
GWSServiceClient gwsServiceClient = new GWSServiceClient(apiBaseDomain);
WorkspaceCreationReq req = new WorkspaceCreationReq();
// 空间名称
req.setName("测试sdk创建空间222255555");
// 空间描述
req.setDescription("自测创建的空间22222111");
// 无限空间
req.setType(WorkspaceType.UNLIMITED.getCode());
// 创建者ID 广联云用户ID 可以为空
req.setCreatorId("6275853124802441678");
// SERVICE_TOKEN为前置准备 步骤3 中获取的应用token
WorkspaceBasicInfoResp workspace = gwsServiceClient.createWorkspace(req, SERVICE_TOKEN);
String apiBaseDomain = "http://apigate.hsifue.cn/gdoc/";
GDocServiceClient client = new GDocServiceClient(apiBaseDomain);
String localFilePath = "/Users/sidney/Downloads/YoudaoNote.dmg";
InputStream fio = new FileInputStream(localFilePath);
// workspaceId为 步骤2创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// 上传到指定的父目录id下
String parentFolderFileId = "ec7dc0dab5c44daeb47a224bc73da20d";
String fileName = "textStreaming.dmg";
// parentFilePath和parentFolderFileId二选一
// parentFilePath的路径会自动补全 比如 /a/b 其中如果/a/b不存在 服务器会自动创建/a和/a/b两级目录
String parentFilePath = "/";
// 文件大小 需要本地提前计算 单位字节
Long fileLength = 100L;
// 从哪个字节开始 一般为空 表示0
Long position = null;
// 保留字段
String digest = null;
// SERVICE_TOKEN为前置准备 步骤3 中获取的应用token
GFile gFile = client.uploadFile(fio, workspaceId,
parentFolderFileId, fileName,
parentFilePath, fileLength, position, digest, SERVICE_TOKEN);
String apiBaseDomain = "http://apigate.hsifue.cn/gdoc/";
GDocServiceClient client = new GDocServiceClient(apiBaseDomain);
// workspaceId为 步骤2创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// 获取指定的父目录id下子文件列表
String parentFolderFileId = "ec7dc0dab5c44daeb47a224bc73da20d";
// parentFilePath和parentFolderFileId二选一
String parentFilePath = "/";
// SERVICE_TOKEN为前置准备 步骤3 中获取的应用token
// Integer pageIndex 第几页
// Integer pageItemCount 每页个数
// orderByType 排序字段 [NAME|TIME]
// order 排序方向 [ASC|DESC]
Pagination<GFile> respData = client.queryFileChildrenByPagination(workspaceId,
parentFolderFileId, parentFilePath, pageIndex, pageItemCount, orderByType, order, SERVICE_TOKEN);
String apiBaseDomain = "http://apigate.hsifue.cn/gdoc/";
GDocServiceClient client = new GDocServiceClient(apiBaseDomain);
// workspaceId为 步骤2创建空间 返回值中的 WorkspaceBasicInfoResp.getId()
String workspaceId = "ec7dc0dab5c44daeb47a224bc73da20d";
// fileId为 上传成功后服务端返回的GFile.getFileId()
String fileId = "ec7dc0dab5c44daeb47a224bc73da20d"
// 此接口返回的是一个下载签名外链 GSignedFile.signedURL 可直接用于下载
GSignedFile data = client.getSignedDownloadUrl(workspaceId,
fileId, null, SERVICE_TOKEN);
说明:SDK方式目前只支持304永利集团集团内部用户
使用已封装好的gdoc-java-sdk、gws-java-sdk访问gdoc功能,使用account-ext-core用来获取token。
主要依赖如下
<!-- gdoc功能 -->
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gws-java-sdk</artifactId>
<version>1.2.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>okio</artifactId>
<groupId>com.squareup.okio</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<artifactId>okio</artifactId>
<groupId>com.squareup.okio</groupId>
<version>${okio.version}</version>
</dependency>
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gdoc-java-sdk</artifactId>
<version>1.8.6-SNAPSHOT</version>
</dependency>
<!-- 用来获取token -->
<dependency>
<artifactId>account-ext-core</artifactId>
<groupId>com.glodon.paas.foundation</groupId>
<version>0.0.9-SNAPSHOT</version>
</dependency>
本演示的pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<okio.version>1.17.2</okio.version>
</properties>
<dependencies>
<!-- gdoc功能 -->
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gws-java-sdk</artifactId>
<version>1.2.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>okio</artifactId>
<groupId>com.squareup.okio</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<artifactId>okio</artifactId>
<groupId>com.squareup.okio</groupId>
<version>${okio.version}</version>
</dependency>
<dependency>
<groupId>com.glodon.paas.foundation</groupId>
<artifactId>gdoc-java-sdk</artifactId>
<version>1.8.6-SNAPSHOT</version>
</dependency>
<!-- 用来获取token -->
<dependency>
<artifactId>account-ext-core</artifactId>
<groupId>com.glodon.paas.foundation</groupId>
<version>0.0.9-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置application.yml
application:
app-key: #您创建的应用的appKey
app-secret: #您创建的应用的appSecret
account-url: http://account.hsifue.cn/
apigate-url: http://apigate.hsifue.cn/gdoc/
workspace-id: # 一般提前创建好
开始使用(以Java SDK为例)
package com.example.demo;
import com.glodon.paas.document.bean.GFile;
import com.glodon.paas.document.bean.GSignedFile;
import com.glodon.paas.document.bean.SignedUrlBehavior;
import com.glodon.paas.document.bean.SignedUrlType;
import com.glodon.paas.foundation.accountCore.AccountConfiguration;
import com.glodon.paas.foundation.accountCore.AccountService;
import com.glodon.paas.foundation.accountCore.service.AccountServiceImpl;
import com.glodon.paas.foundation.sdk.gdoc.GDocServiceClient;
import com.glodon.paas.foundation.sdk.gws.GWSServiceClient;
import com.glodon.paas.gws.bean.WorkspaceCreationReq;
import com.glodon.paas.gws.oauth2.resp.WorkspaceBasicInfoResp;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.InputStream;
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
@Value("${application.app-key}")
private String appKey;
@Value("${application.app-secret}")
private String appSecret;
@Value("${application.account-url}")
private String accountUrl;
@Value("${application.apigate-url}")
private String apigatetUrl;
@Value("${application.workspace-id}")
private String workspaceId;
@Bean
AccountService accountService() {
return new AccountServiceImpl(new AccountConfiguration(null, appKey, appSecret, accountUrl, false));
}
@Override
public void run(String... args) throws Exception {
String accessToken = accountService().getServiceToken().getAccessToken();
// 1 workspaceId 应提前创建好,此处为了演示,临时创建
if (StringUtils.isEmpty(workspaceId)) {
workspaceId = createWorkspace("test", accessToken);
}
System.out.println("workspaceId is " + workspaceId);
GDocServiceClient client = new GDocServiceClient(apigatetUrl);
File file = new File("E:\\a.zip");
String containerId = workspaceId;
String parentId = null;
String fileName = null;
String filePath = "mypath/" + file.getName();
Long size = file.length();
Long position = null;
String digest = null;
// 2 上传文件
GFile gfile = client.uploadFile(file, containerId, parentId, fileName, filePath, size, position, digest, accessToken);
String fileId = gfile.getFileId();
System.out.println("upload fileId is " + fileId);
// 3 下载文件
String loaclFile = "E:\\f.zip";
InputStream is = client.downloadFileByFileId(containerId, fileId, null, accessToken);
FileUtils.copyInputStreamToFile(is, new File(loaclFile));
System.out.println("download to " + loaclFile);
// 4 分享链接
Integer versionIndex = null;
SignedUrlType type = SignedUrlType.PUBLIC;
SignedUrlBehavior behavior = SignedUrlBehavior.DOWNLOAD;
Integer lease = 60; // 这个指过期时间
GSignedFile gSignedFile = client.getSignedURLByFileId(workspaceId, fileId, versionIndex, type, behavior, lease, accessToken);
String url = gSignedFile.getSignedURL();
System.out.println("signed url is " + url);
}
private String createWorkspace(String name, String accessToken) {
GWSServiceClient client = new GWSServiceClient();
WorkspaceCreationReq workspaceCreationReq = new WorkspaceCreationReq();
workspaceCreationReq.setName("name");
workspaceCreationReq.setType(new Byte((byte) 2));
workspaceCreationReq.setPrivilegeType(0);
WorkspaceBasicInfoResp workspaceBasicInfoResp = client.createWorkspace(workspaceCreationReq, accessToken);
return workspaceBasicInfoResp.getId();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
# 对demo中涉及到的api进行封装
# gdocclient_sdk_python.py
import requests
import base64
import json
import time
import os
import logging
import traceback
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logger = logging.getLogger('GDocClient')
class GDocClient:
def __init__(self, appKey, appSecret, workspaceId, accountServer = "http://account.hsifue.cn", apigateServer = "http://apigate.hsifue.cn"):
self._accountUrl = accountServer + "/oauth2/token?grant_type=client_credentials"
self._apigateUrl = apigateServer
self._fileDataUrl = self._apigateUrl + '/gdoc/v3/doc/{}/file/data'
self._fileWorkspaceUrl = self._apigateUrl + '/gdoc/gws/v4/service/workspaces'
self._signedUrl = self._apigateUrl + '/gdoc/v3/doc/{}/file/signedURL?fileId={}&lease={}'
k = appKey + ':' + appSecret
self._basicAuth = base64.b64encode(k.encode()).decode()
self._accessToken = None
self._expiredIn = None
self._accessTokenStartTime = None
self._workspaceId = workspaceId
def _checkToken(self):
if self._accessToken == None:
r = requests.post(self._accountUrl, headers={'Authorization': 'Basic ' + self._basicAuth})
data = json.loads(r.text)
logger.info("_checkToken -> %s", data)
if r.status_code == 200:
self._accessToken = data['access_token']
self._expiredIn = data['expires_in']
self._accessTokenStartTime = time.time()
else:
raise Exception('check token fail {}' % r.text)
return self._accessToken != None
def setWorkspaceId(self, workspaceId):
self._workspaceId = workspaceId
def createWorkspace(self, name):
r"""创建空间.
:param name: 空间名称.
:return: id 空间id
:rtype: string
"""
if self._checkToken():
url = self._fileWorkspaceUrl
data = {
"name": name,
"type": "2",
"privilegeType": "0"
}
r = requests.post(url, headers={'Authorization': 'Bearer ' + self._accessToken, 'Content-Type':'application/json'}, data=json.dumps(data))
data = json.loads(r.text)
logger.info("createWorkspace -> %s", data)
if r.status_code == 200 and data['code'] == 0:
return data['data']['id']
else:
raise Exception('createWorkspace fail {}' % data)
def upload(self, localFile, fileParentPath = None):
r"""上传文件.
:param localFile: 本地文件路径.
:param fileParentPath: 服务器文件夹.
:return: fileId 上传后的云端文件id
:rtype: string
"""
if self._workspaceId == None:
raise Exception('you should create container first')
if self._checkToken():
fsize = os.path.getsize(localFile)
path = os.path.basename(localFile) if fileParentPath == None else fileParentPath + '/' + os.path.basename(localFile)
url = self._fileDataUrl.format(self._workspaceId) + '?filePath={}&size={}'.format(path, fsize)
files = {'name': open(localFile, 'rb')}
r = requests.post(url, headers={'Authorization': 'Bearer ' + self._accessToken}, files=files)
data = json.loads(r.text)
logger.info("upload -> %s", data)
if r.status_code == 200 and data['code'] == 0:
return data['data']['fileId']
else:
raise Exception('upload fail {}'.format(data))
def getSignedUrl(self, fileId, expiresIn):
r"""获取下载链接.
:param fileId: 云端文件id.
:param expiresIn: 有效期(秒).
:return: url 下载链接
:rtype: string
"""
if self._workspaceId == None:
raise Exception('you should create container first')
if self._checkToken():
url = self._signedUrl.format(self._workspaceId, fileId, expiresIn)
r = requests.get(url, headers={'Authorization': 'Bearer ' + self._accessToken})
data = json.loads(r.text)
logger.info("getSignedUrl -> %s", data)
if r.status_code == 200 and data['code'] == 0:
return data['data']['signedURL']
else:
raise Exception('getSignedUrl fail {}'.format(data))
def download(self, fileId, saveToFile):
r"""下载文件.
:param fileId: 云端文件id.
:param saveToFile: 保存到本地文件.
:return:
:rtype: string
"""
if self._workspaceId == None:
raise Exception('you should create container first')
if self._checkToken():
url = self._fileDataUrl.format(self._workspaceId) + '?fileId={}'.format(fileId)
r = requests.get(url, headers={'Authorization': 'Bearer ' + self._accessToken})
if r.status_code != 200:
raise Exception('download fail {}'.format(r.text))
logger.info("download -> %s", saveToFile)
with open(saveToFile, "wb") as infile:
infile.write(r.content)
开始使用
from gdocclient_sdk_python.py import GDocClient
app_key = #您创建的应用的appKey
app_secret = #您创建的应用的appSecret
f = "E:\\a.zip"
client = GDocClient(app_key, app_secret, None)
# 1 通常workspace只创建一次,保留此workspaceId使用
workspaceId = client.createWorkspace("test")
print("workspaceId --> ", workspaceId)
client.setWorkspaceId(workspaceId)
# 2 上传文件
fileId = client.upload(f)
print("fileId --> ", fileId)
# 3 生成分享链接
url = client.getSignedUrl(fileId, 60)
print("url --> ", url)
# 4 直接下载文件
client.download(fileId, "E:\\c.zip")
print("done --> ")