13 Commits
dev ... master

Author SHA1 Message Date
Mr.Yang
03dbf3ad93 Merge pull request #18 from PicGo/dev
build:build 1.9.2+24
2020-12-30 11:59:30 +08:00
Mr.Yang
8795c60503 Merge pull request #17 from PicGo/dev
pre release v1.9.2+23
2020-12-29 23:49:05 +08:00
hackycy
8f4957d4e4 Merge branch 'dev' 2020-12-10 10:44:30 +08:00
Mr.Yang
bd719688c3 Merge pull request #9 from PicGo/dev
pr:merge dev
2020-11-16 12:08:20 +08:00
hackycy
534c41a286 Merge branch 'dev' 2020-08-16 13:10:53 +08:00
hackycy
bb20eb740e Merge branch 'dev' 2020-07-31 13:56:03 +08:00
hackycy
95a3dc3182 Merge branch 'dev' 2020-07-27 14:56:33 +08:00
hackycy
0c6d7b76d3 Merge branch 'dev' 2020-07-27 14:46:01 +08:00
hackycy
c1721efb56 Merge branch 'dev' 2020-07-23 12:10:24 +08:00
hackycy
1193b9a4b1 Merge branch 'dev' 2020-07-22 11:55:22 +08:00
hackycy
bb4caba42b Merge branch 'dev' 2020-07-21 10:44:54 +08:00
Mr.Yang
807e94159c Merge pull request #7 from PicGo/dev
Merge Dev
2020-07-20 15:34:13 +08:00
Mr.Yang
93d3c3ab15 Merge pull request #6 from PicGo/dev
merge dev
2020-07-20 14:53:06 +08:00
27 changed files with 108 additions and 156 deletions

View File

@@ -39,9 +39,9 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
# 应用截图
![上传页面](https://github.static.si-yee.com/picgo/5E62E0A4-5A93-4C57-B090-E09F4100B755_L0_001_origin.IMG_8818.JPG)
![上传页面](https://github.static.si-yee.com/image_picker_82452E23-BE11-4712-BFBA-8E93038DB410-3851-00000340B21CCF62.png)
<img src="https://github.static.si-yee.com/picgo/repo_use.gif" width="300px" />
![管理页面Gif](https://github.static.si-yee.com/picgo/repo_use.gif)
# 下载安装
@@ -56,51 +56,9 @@ Flutter-PicGo: 一个用于快速上传图片并获取图片URL链接的**手机
目前仅支持iOS与Android端,由于部分插件例如[sqflite](https://pub.dev/packages/sqflite)不支持Web端,所以应用也并不支持Web端。
# F & Q
# 注意事项
## 简单使用说明
**上传前需要先去`设置` -> `图床设置`下设置图床的配置信息并设置默认上传图床,以及给予App所申请的权限(相册),否则无法进行上传。**
## 已不可用图床
- 牛图网(官网也无法使用)
## 关于Github图片上传问题
由于国内访问Github访问速度慢的原因,API访问也会经常出错,建议切换别的图床进行使用。
或者配置host提升访问速度,这里提供一种方式:
<img src="https://raw.githubusercontent.com/hackycy/flutter-picgo/dev/docs/hostconfig.jpeg" width="200px" />
在路由器(图中为小米的路由器)里面配置hosts,具体配置可以查看[Github520](https://github.com/521xueweihan/GitHub520)。
路由器配置hosts后连接Wi-Fi可以显著提升API的访问能力。
## 将配置信息转二维码供App扫码
这里拿Github举例:
GitHub的配置JSON(与桌面版Picgo配置信息一致)如下
``` json
{
"github": {
"branch": "",
"customUrl": "",
"path": "",
"repo": "",
"token": ""
}
}
```
想要获取其它的配置信息可以在App随便填一下然后再导出配置,复制粘贴出来填写好配置信息,将这整段json去转换成二维码保存,例如[草料](https://cli.im)。在App扫码就能直接转换好配置了,不用再一项一项的填写。
> 已经使用过桌面版[PicGo](https://github.com/Molunerfinn/PicGo)则更加方便,直接使用桌面版导出二维码即可。
>
> 暂不支持备份图床已上传的图片。
- [注意事项](https://github.com/PicGo/flutter-picgo/blob/dev/docs/注意事项.md)
# 有问题或者有更好的建议
@@ -110,9 +68,8 @@ GitHub的配置JSON(与桌面版Picgo配置信息一致)如下
# 相关
- [PicGo](https://github.com/Molunerfinn/PicGo):PicGo 的桌面版
- [PicGo](https://github.com/Molunerfinn/PicGo) : PicGo 的桌面版
- [vs-picgo](https://github.com/PicGo/vs-picgo):PicGo 的 VS Code 版。
- [sf-nest-admin](https://github.com/hackycy/sf-nest-admin):基于NestJs编写的带七牛文件管理的后台权限系统
# 致谢

View File

@@ -1,10 +1,10 @@
{
"iOS": {
"versionName": "1.9.2",
"versionCode": "24"
"versionName": "1.9.1",
"versionCode": "22"
},
"Android": {
"versionName": "1.9.2",
"versionCode": "24"
"versionCode": "23"
}
}

17
docs/注意事项.md Normal file
View File

@@ -0,0 +1,17 @@
### 功能建议或BUG提交
> 请尽量在Github页面中发起[issue](https://github.com/PicGo/flutter-picgo/issues),否则在其他地方比较难以管理和收集建议。
### 关于Github图片上传问题
> 由于国内访问Github慢的原因,API访问也会经常出错,建议切换别的图床进行使用。
>
> 或者配置host提升访问速度,这里提供一种方式:
>
> ![](https://raw.githubusercontent.com/hackycy/flutter-picgo/dev/docs/hostconfig.jpeg)
>
> 在路由器里面配置hosts,具体配置可以查看[Github520](https://github.com/521xueweihan/GitHub520)。
>
> 路由器配置hosts后连接Wi-Fi可以显著提升API的访问能力。

View File

@@ -144,10 +144,7 @@ class QiniuApi {
/// 七牛管理验签拦截器
class QiniuInterceptor extends InterceptorsWrapper {
@override
Future onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
Future onRequest(RequestOptions options) async {
if (options.path.contains(QiniuApi.BASE_URL)) {
String ak = '${options.extra[QiniuApi.accessKey]}';
String sk = '${options.extra[QiniuApi.secretKey]}';
@@ -174,6 +171,6 @@ class QiniuInterceptor extends InterceptorsWrapper {
'Authorization': 'QBox $accessToken',
});
}
return handler.next(options);
return options;
}
}

View File

@@ -88,10 +88,7 @@ class TcyunApi {
/// TcYun验签拦截器
class TcyunInterceptor extends InterceptorsWrapper {
@override
Future onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
Future onRequest(RequestOptions options) async {
if (options.path.contains(TcyunApi.BASE_URL)) {
/// 生成 KeyTime
var keytime = TcyunApi.buildKeyTime();
@@ -169,6 +166,6 @@ class TcyunInterceptor extends InterceptorsWrapper {
headers.addAll({'Authorization': realSign});
options.headers = headers;
}
return handler.next(options);
return options;
}
}

View File

@@ -68,10 +68,7 @@ class UpyunApi {
class UpyunInterceptor extends InterceptorsWrapper {
@override
Future onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
Future onRequest(RequestOptions options) async {
if (options.path.contains(UpyunApi.BASE_URL.replaceFirst('http://', ''))) {
/// 请求方式,如:GET、POST、PUT、HEAD 等
String method = options.method.toUpperCase();
@@ -93,6 +90,6 @@ class UpyunInterceptor extends InterceptorsWrapper {
'Authorization': 'UPYUN $operator:$realAuth',
});
}
return handler.next(options);
return options;
}
}

View File

@@ -83,14 +83,14 @@ class ManageItem extends StatelessWidget {
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.circular(8)),
borderRadius: BorderRadiusDirectional.circular(2)),
child: ExtendedImage.network(
this.url,
width: 50,
height: 50,
fit: BoxFit.cover,
cache: true,
// border: Border.all(color: Colors.grey, width: 1.0),
border: Border.all(color: Colors.grey, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(8)),
loadStateChanged: (state) => defaultLoadStateChanged(state),
),

View File

@@ -63,13 +63,13 @@ class _UploadItemState extends State<UploadItem> implements UploadItemContract {
child: Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadiusDirectional.circular(8)),
borderRadius: BorderRadiusDirectional.circular(2)),
child: ExtendedImage.file(
File(widget.file.path),
width: 50,
height: 50,
fit: BoxFit.cover,
// border: Border.all(color: Colors.grey, width: 1.0),
border: Border.all(color: Colors.grey, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(8)),
loadStateChanged: (state) => defaultLoadStateChanged(state),
),

View File

@@ -2,7 +2,6 @@ import 'dart:io';
import 'dart:math';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_picgo/model/uploaded.dart';
@@ -18,8 +17,8 @@ class ImagePreviewUtils {
Navigator.push(
context,
Platform.isAndroid
? MaterialPageRoute(builder: (_) => page)
: CupertinoPageRoute(builder: (_) => page),
? TransparentMaterialPageRoute(builder: (_) => page)
: TransparentCupertinoPageRoute(builder: (_) => page),
);
}
@@ -31,8 +30,8 @@ class ImagePreviewUtils {
Navigator.push(
context,
Platform.isAndroid
? MaterialPageRoute(builder: (_) => page)
: CupertinoPageRoute(builder: (_) => page));
? TransparentMaterialPageRoute(builder: (_) => page)
: TransparentCupertinoPageRoute(builder: (_) => page));
}
}

View File

@@ -21,7 +21,7 @@ class PermissionUtils {
title: Text('警告'),
content: Text(text),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('去设置'),
onPressed: () {
openAppSettings();

View File

@@ -77,7 +77,7 @@ class GiteeImageUpload implements ImageUploadStrategy {
await ImageUploadUtils.saveUploadedItem(uploadedItem);
return uploadedItem;
} on DioError catch (e) {
if (e.type == DioErrorType.response &&
if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('400') > 0) {
throw GiteeError(error: '文件已存在!');
} else {

View File

@@ -64,7 +64,7 @@ class GithubImageUpload implements ImageUploadStrategy {
throw GithubError(error: '读取配置文件错误!请重试');
}
} on DioError catch (e) {
if (e.type == DioErrorType.response &&
if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('422') > 0) {
throw GithubError(error: '文件已存在!');
} else {

View File

@@ -31,16 +31,16 @@ class QiniuImageUpload extends ImageUploadStrategy {
}
return uploaded;
} on DioError catch (e) {
if (e.type == DioErrorType.response &&
if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('400') > 0) {
throw QiniuError(error: '400 请求报文格式错误');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('401') > 0) {
throw QiniuError(error: '401 管理凭证无效');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('599') > 0) {
throw QiniuError(error: '599 服务端操作失败');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('612') > 0) {
throw QiniuError(error: '612 待删除资源不存在');
} else {
@@ -88,16 +88,16 @@ class QiniuImageUpload extends ImageUploadStrategy {
await ImageUploadUtils.saveUploadedItem(uploadedItem);
return uploadedItem;
} on DioError catch (e) {
if (e.type == DioErrorType.response &&
if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('400') > 0) {
throw QiniuError(error: '400 请求报文格式错误');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('401') > 0) {
throw QiniuError(error: '401 管理凭证无效');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('599') > 0) {
throw QiniuError(error: '599 服务端操作失败');
} else if (e.type == DioErrorType.response &&
} else if (e.type == DioErrorType.RESPONSE &&
e.error.toString().indexOf('612') > 0) {
throw QiniuError(error: '612 待删除资源不存在');
} else {

View File

@@ -10,10 +10,8 @@ class PageNotFound extends StatelessWidget {
),
body: Container(
child: Center(
child: OutlinedButton(
style: ButtonStyle(
side:
MaterialStateProperty.all(BorderSide(color: Colors.blue))),
child: OutlineButton(
color: Colors.blue,
child: Text('关闭'),
onPressed: () {
Application.router.pop(context);

View File

@@ -129,7 +129,7 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
height: 150,
fit: BoxFit.cover,
cache: true,
// border: Border.all(color: Colors.grey, width: 1.0),
border: Border.all(color: Colors.grey, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(8)),
loadStateChanged: (state) =>
defaultLoadStateChanged(state, iconSize: 30),
@@ -215,7 +215,7 @@ class _AlbumPageState extends State<AlbumPage> implements AlbumPageContract {
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context);

View File

@@ -92,11 +92,9 @@ class _GiteeRepoPageState extends BaseLoadingPageState<GiteeRepoPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Theme.of(context).accentColor)),
RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('刷新'),
onPressed: () {
setState(() {
@@ -166,7 +164,7 @@ class _GiteeRepoPageState extends BaseLoadingPageState<GiteeRepoPage>
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context, true);

View File

@@ -92,11 +92,9 @@ class _GithubRepoPageState extends BaseLoadingPageState<GithubRepoPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Theme.of(context).accentColor)),
RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('刷新'),
onPressed: () {
setState(() {
@@ -166,7 +164,7 @@ class _GithubRepoPageState extends BaseLoadingPageState<GithubRepoPage>
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context, true);

View File

@@ -47,11 +47,9 @@ class _LskyRepoPageState extends BaseLoadingPageState<LskyRepoPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Theme.of(context).accentColor)),
RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('刷新'),
onPressed: () {
setState(() {
@@ -138,7 +136,7 @@ class _LskyRepoPageState extends BaseLoadingPageState<LskyRepoPage>
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context, true);

View File

@@ -52,11 +52,9 @@ class _QiniuRepoPageState extends BaseLoadingPageState<QiniuRepoPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Theme.of(context).accentColor)),
RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('刷新'),
onPressed: () {
setState(() {
@@ -123,7 +121,7 @@ class _QiniuRepoPageState extends BaseLoadingPageState<QiniuRepoPage>
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context, true);

View File

@@ -120,11 +120,9 @@ class _SMMSRepoPageState extends BaseLoadingPageState<SMMSRepoPage>
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Theme.of(context).accentColor)),
RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('刷新'),
onPressed: () {
setState(() {
@@ -183,7 +181,7 @@ class _SMMSRepoPageState extends BaseLoadingPageState<SMMSRepoPage>
title: Text('确定删除吗'),
content: Text('删除后无法恢复'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context, true);

View File

@@ -50,12 +50,9 @@ abstract class BasePBSettingPageState<T extends StatefulWidget>
child: Row(
children: <Widget>[
Expanded(
child: ElevatedButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all(Colors.white),
backgroundColor: MaterialStateProperty.all(
Theme.of(context).accentColor)),
child: RaisedButton(
color: Theme.of(context).accentColor,
textColor: Colors.white,
child: Text('保存'),
onPressed: () {
if (validate) {
@@ -66,12 +63,9 @@ abstract class BasePBSettingPageState<T extends StatefulWidget>
),
SizedBox(width: 5.0),
Expanded(
child: ElevatedButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all(Colors.white),
backgroundColor:
MaterialStateProperty.all(Colors.greenAccent)),
child: RaisedButton(
color: Colors.greenAccent,
textColor: Colors.white,
child: Text('设为默认图床'),
onPressed: () {
if (validate) {

View File

@@ -50,7 +50,7 @@ class _PBSettingPageState extends State<PBSettingPage>
'在PC端已经配置好的用户可以使用PicGo新版的生成图床配置二维码功能。\n\n' +
'然后使用Flutter-PicGo直接扫描即可进行配置转换。'),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('已了解,去扫描'),
onPressed: () {
Navigator.pop(context);

View File

@@ -154,7 +154,7 @@ class _HandleUploadPageState extends State<HandleUploadPage> {
),
),
actions: <Widget>[
TextButton(
FlatButton(
child: Text('确定'),
onPressed: () {
Navigator.pop(context);

View File

@@ -23,22 +23,23 @@ environment:
dependencies:
flutter:
sdk: flutter
shared_preferences: ^2.0.5
dio: ^4.0.0
package_info: ^2.0.0
shared_preferences: ^0.5.12+4
dio: ^3.0.9
package_info: ^0.4.1
sqflite: ^1.3.2+1
fluro: ^2.0.3
fluro: ^1.7.7
toast: ^0.1.5
json_serializable: ^3.3.0
url_launcher: ^5.7.10
permission_handler: ^5.0.1
barcode_scan: ^3.0.1
provider: ^5.0.0
crypto: ^3.0.1
provider: ^4.1.3
crypto: ^2.1.4
flutter_local_notifications: ^3.0.1+4
pull_to_refresh: ^1.6.5
wechat_assets_picker: ^5.1.3
extended_image: ^4.0.1
pull_to_refresh: ^1.6.2
characters: ^1.0.0
wechat_assets_picker: ^4.2.2
extended_image: ^1.5.0
# The following adds the Cupertino Icons font to your application.

View File

@@ -17,14 +17,14 @@ main() {
var sign = AliyunApi.buildSignature('LTAIsXml0iczvY0J',
'yw8eO9Fa9Py2GAPRGG8N3GPKCeKCXl', 'PUT', 'zjyzy', 'test.txt');
try {
await NetUtils.getInstance().put(
Response res = await NetUtils.getInstance().put(
'https://zjyzy.oss-cn-shenzhen.aliyuncs.com/test.txt',
options: Options(headers: {
'Authorization': sign,
'Date': HttpDate.format(new DateTime.now()),
}, contentType: 'application/x-www-form-urlencoded'),
);
} on DioError catch (_) {}
} on DioError catch (e) {}
});
test('测试FormData提交图片', () async {
@@ -43,7 +43,7 @@ main() {
var sign = hmacsha1.convert(utf8.encode(originSign));
var encodeSign = base64.encode(sign.bytes);
try {
await NetUtils.getInstance().post(
Response res = await NetUtils.getInstance().post(
'https://zjyzy.oss-cn-shenzhen.aliyuncs.com',
data: FormData.fromMap({
'key': 'logo.png',
@@ -53,6 +53,6 @@ main() {
'file': await MultipartFile.fromFile(pathname, filename: 'logo.png')
}),
options: Options(contentType: Headers.formUrlEncodedContentType));
} on DioError catch (_) {}
} on DioError catch (e) {}
});
}

View File

@@ -4,8 +4,10 @@ import 'package:flutter_test/flutter_test.dart';
main() {
test('测试UpToken生成', () {
String policy = QiniuApi.generatePutPolicy('image', 'test.png');
QiniuApi.generateUpToken('CRd7Wa4PuSGvs4ArToPTLBMCigGGUY3sk3F8oc8W',
'f2Jkrlyea5s8h8gLEToa9-k895GNM-BlmQ2RfxwU', policy);
var token = QiniuApi.generateUpToken(
'CRd7Wa4PuSGvs4ArToPTLBMCigGGUY3sk3F8oc8W',
'f2Jkrlyea5s8h8gLEToa9-k895GNM-BlmQ2RfxwU',
policy);
});
test('测试AuthToken生成', () {

View File

@@ -1,5 +1,8 @@
import 'dart:io';
import 'package:flutter_picgo/api/tcyun_api.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart' as path;
main() {
test('测试生成 KeyTime', () {});
@@ -19,11 +22,11 @@ main() {
test('PostObjecy 提交', () async {
try {
// String pathname = path.joinAll(
// [Directory.current.path, '..\\assets\\' 'images', 'logo.png']);
// String keyTime = TcyunApi.buildKeyTime();
// String policy = TcyunApi.buildPolicy('ap-nanjing', 'logo.png',
// 'AKIDvb0B9rqfeOr44kt2ar46rO2cwzl6JwUk', keyTime);
String pathname = path.joinAll(
[Directory.current.path, '..\\assets\\' 'images', 'logo.png']);
String keyTime = TcyunApi.buildKeyTime();
String policy = TcyunApi.buildPolicy('ap-nanjing', 'logo.png',
'AKIDvb0B9rqfeOr44kt2ar46rO2cwzl6JwUk', keyTime);
// TcyunApi.postObject(
// 'test-1253954259',
// 'ap-nanjing',