这里是利用钉钉jsapi 提供的chooseImage(拍照或者选择本地照片),compressImage(压缩图片),uploadFile(上传本地资源到开发者服务器)接口来完成对图片的上传。
第一步,安装jsapi
npm i dingtalk-jsapi
第二步,鉴权
钉钉提供了很多的api,一部分需要鉴权,不部分是不需要的。例如dd.scan是不需要鉴权的,dd.chooseImage就需要鉴权(虽然官方文档上标注不需要,但实际需要)。
import * as dd from 'dingtalk-jsapi';
function apiConfig(path: string) {
// 通过后端获取签名所需参数
ajax(path).then((res) => {
if (res.data.success) {
const { agentId, timeStamp, nonceStr, signature } = res.data.content;
dd.config({
agentId,
corpId: loginUtil.getCorpId(),
timeStamp,
nonceStr,
signature,
type: 0,
jsApiList: ['chooseImage'], // 这里要填写需要鉴权的api
});
dd.error((err) => {
alert('dingTalk config error: ' + JSON.stringify(err))
}); // 该方法必须带上,用来捕获鉴权出现的异常信息,否则不方便排查出现的问题
}
});
}
第三步,唤起相机或相册选择图
dd.chooseImage({
count: 9,
sourceType: ['camera', 'album'],
success: (res) => {
// 返回结果
const { files, filePaths } = res;
},
fail: (error) => {
if (Number(error.errorCode) === -1 || Number(error.errorCode) === 11) {
console.log('chooseImage cancel');
} else if (Number(error.errorCode) === 7) {
alert('chooseImage no permission info');
} else {
alert('chooseImage=>' + JSON.stringify(error));
}
},
complete: () => {}
});
// 结果 数据结构
/*{
"files": [
{
"path": "https://resource/MzNjMmEwN2FjMjg0YTBkYTI4NTdlYmJhNTI3NDhlZWU=.image",
"size": 327622,
"fileType": "jpg"
},
{
"path": "https://resource/ZDNmODkzM2RhNWQwMWI4NzEwOGFlY2U0NzJkY2ZmZjY=.image",
"size": 317501,
"fileType": "jpg"
}
],
"filePaths": [
"https://resource/MzNjMmEwN2FjMjg0YTBkYTI4NTdlYmJhNTI3NDhlZWU=.image",
"https://resource/ZDNmODkzM2RhNWQwMWI4NzEwOGFlY2U0NzJkY2ZmZjY=.image"
]
}*/
第四步,压缩设置(根据实际情况,可以跳过)
dd.compressImage({
filePaths, // 上一步获取结果的filePaths
compressLevel: 3, //压缩级别,支持 0 ~ 4 的整数,默认 4。 0:低质量。 1:中等质量。 2:高质量。 3:不压缩。 4:根据网络适应。
success: (res) => {
// 压缩结果
const { filePaths } = res;
},
fail: () => {},
complete: () => {}
});
第五步,上传到阿里云
官方文档指出为了您的数据安全,建议使用签名方式上传文件。所以这里不得下载两个库。
npm i crypto-js js-base64
使用dd.uploadFile上传图片
import { Base64 } from 'js-base64';
import crypto from 'crypto-js';
import * as dd from 'dingtalk-jsapi';
// 计算签名。
function computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(
crypto.HmacSHA1(canonicalString, accessKeySecret)
);
}
interface DingTalkFileVo {
path: string;
size: number;
fileType: string;
}
//设置上传路径 我这里是是后端设置的路径加上uuid
function getPathDingTalk(file: DingTalkFileVo, path?) {
const randomId = uuidv4();
let key = '';
if (path) {
key = path;
} else {
key = 'image/';
}
return key + randomId + '.' + file.fileType;
}
interface DingTalkUpladFileParam {
url: string;
header?: { [key: string | number]: any };
fileName: string;
filePath: string;
fileType: string;
formData?: { [key: string | number]: any };
}
function uploadFile() {
getOssToken().then((res) => {
const host = res.data.content.host;
const params = {} as DingTalkUpladFileParam;
params.fileName = 'file';
params.filePath = file.path;
params.url = this.host;
params.fileType = file.fileType;
const date = new Date();
date.setHours(date.getHours() + 24);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
['content-length-range', 0, 50 * 1024 * 1024]
]
};
const policy = Base64.encode(JSON.stringify(policyText)); // policy必须为base64的string。
const signature = computeSignature(.data.content.accessKeySecret,policy);
params.formData = {
OSSAccessKeyId: res.data.content.accessKeyId,
'x-oss-security-token': res.data.content.securityToken,
key: getPathDingTalk(file, res.data.content.path),
signature,
policy,
success_action_status: '200' // 让服务端返回200,不然,默认会返回204
};
params.header = {
'x-oss-object-acl': 'public-read' // 指定Object的访问权限
};
dd.uploadFile(params).then((response) => {
// 上传结果
const result = host + '/' + response
});
});
}
参考官方文档
钉钉客户端SDKhttps://open.dingtalk.com/document/orgapp/read-before-development
阿里云对象存储https://help.aliyun.com/zh/oss/?spm=a2c4g.11186623.0.0.6642b9199qnUMt