卡片短信模板中使用的图片、视频等素材资源可上传到OSS文件系统保存。
使用须知
本章节调用的不是卡片短信API接口,您不需要使用阿里云账号进行鉴权,直接使用GetOSSInfoForCardTemplate接口返回Signature、Policy、AccessKeyId,通过HTTP方式即可上传图片、视频素材资源到卡片短信OSS存储空间。
文件上传
调用接口前需配置环境变量,通过环境变量读取访问凭证。AccessKey ID和AccessKey Secret的环境变量名:SMS_ACCESS_KEY_ENV 、SMS_ACCESS_KEY_SECRET_ENV。配置详情请参见配置访问凭证。
OSS文件上传提供了前端(JS)和后端(JAVA)两种方式,具体操作请参考文件上传。
JS端文件上传
在该页面,下载步骤2提供的客户端源码(多媒体上传组件plupload)。
参考JS上传代码示例,快速开发一个OSS文件上传工具。
accessid = System.getenv("SCA_AK_ENV") host = 'https://example.aliyundoc.com policyBase64 = '****eHBpcmF0aW9uIjoiMjAyMS0wOS0wM1QxNjo0NDoyNC44NTFaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIxMzQ0MzcxLyJdXX0=' signature = 'wQ5XTtBJRpDMcIjXQB8ma06****=' filename = '' key = '1344371/' //以 'StartPath/' 开头 expire = 1630652012 g_object_name = '' g_object_name_type = '' now = timestamp = Date.parse(new Date()) / 1000; function check_object_radio() { var tt = document.getElementsByName('myradio'); for (var i = 0; i < tt.length ; i++ ) { if(tt[i].checked) { g_object_name_type = tt[i].value; break; } } } function random_string(len) { len = len || 32; var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; var maxPos = chars.length; var pwd = ''; for (i = 0; i < len; i++) { pwd += chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } function get_suffix(filename) { pos = filename.lastIndexOf('.') suffix = '' if (pos != -1) { suffix = filename.substring(pos) } return suffix; } function calculate_object_name(filename) { if (g_object_name_type == 'local_name') { g_object_name += "${filename}" } else if (g_object_name_type == 'random_name') { suffix = get_suffix(filename) g_object_name = key + random_string(10) + suffix } return '' } function get_uploaded_object_name(filename) { if (g_object_name_type == 'local_name') { tmp_name = g_object_name tmp_name = tmp_name.replace("${filename}", filename); return tmp_name } else if(g_object_name_type == 'random_name') { return g_object_name } } function set_upload_param(up, filename, ret) { g_object_name = key; if (filename != '') { suffix = get_suffix(filename) calculate_object_name(filename) } new_multipart_params = { 'key' : g_object_name, 'policy': policyBase64, 'OSSAccessKeyId': accessid, 'success_action_status' : '200', //让服务端返回200,不然,默认会返回204 'signature': signature, }; up.setOption({ 'url': host, 'multipart_params': new_multipart_params }); up.start(); } var uploader = new plupload.Uploader({ runtimes : 'html5,flash,silverlight,html4', browse_button : 'selectfiles', //multi_selection: false, container: document.getElementById('container'), flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf', silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap', url : 'http://oss.aliyuncs.com', filters: { mime_types : [ //只允许上传图片和zip文件 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip,rar" } ], max_file_size : '10mb', //最大只能上传10MB的文件 prevent_duplicates : true //不允许选取重复文件 }, init: { PostInit: function() { document.getElementById('ossfile').innerHTML = ''; document.getElementById('postfiles').onclick = function() { set_upload_param(uploader, '', false); return false; }; }, FilesAdded: function(up, files) { plupload.each(files, function(file) { document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>' +'<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>' +'</div>'; }); }, BeforeUpload: function(up, file) { check_object_radio(); set_upload_param(up, file.name, true); }, UploadProgress: function(up, file) { var d = document.getElementById(file.id); d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>"; var prog = d.getElementsByTagName('div')[0]; var progBar = prog.getElementsByTagName('div')[0] progBar.style.width= 2*file.percent+'px'; progBar.setAttribute('aria-valuenow', file.percent); }, FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name) + ' 回调服务器返回的内容是:' + info.response; } else if (info.status == 203) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '上传到OSS成功,但是oss访问用户设置的上传回调服务器失败,失败原因是:' + info.response; } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }, Error: function(up, err) { if (err.code == -600) { document.getElementById('console').appendChild(document.createTextNode("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小")); } else if (err.code == -601) { document.getElementById('console').appendChild(document.createTextNode("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型")); } else if (err.code == -602) { document.getElementById('console').appendChild(document.createTextNode("\n这个文件已经上传过一遍了")); } else { document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response)); } } } }); uploader.init();
修改JS上传代码实例中OSS参数的设置,数据来源于获取OSS上传信息GetOSSInfoForCardTemplate接口的调用结果,对应关系详见下表。
JS参数
对应OSS结果数据
示例
accessid
Data.AccessKeyId
System.getenv("SCA_AK_ENV")
host
Data.Host
https://example.aliyundoc.com
policyBase64
Data.Policy
eyJleHBpcmF0aW9uIjoiMjAyMS0wOS0wM1QxNjo0NDoyNC44NTFaIiwiY29uZGl0aW9ucyI6W1siY29ud****
signature
Data.Signature
wQ5XTtBJRpDMcIjXQB8ma****
key
Data.StartPath+/
以StartPath开头后面添加/
示例:1344371/
上传文件,提交资源到OSS并获得返回结果。
组装并获得OSSKey,组装规则:
oss://bucket/startPath/filenameBucket = GetOSSInfoForCardTemplate接口返回的Data.Bucket (取值alicom-cardsms-resources)startPath/filename
可以从上一步的返回结果object name后面的文件地址截取,也可以自行组装。
OSSKey示例:oss://alicom-cardsms-resources/1344371****/111222.jpg
JAVA端上传文件
JAVA OSS上传文件示例:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency>
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5.3</version> </dependency>
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.0</version> </dependency>
import org.apache.commons.codec.binary.Base64; import javax.activation.MimetypesFileTypeMap; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; public class OSSSample { private String accessKeyId = System.getenv("SCA_AK_ENV") private String signature = "sQtVRyeiajpq+4f826hx00xv/zg="; private String policy = "****eHBpcmF0aW9uIjoiMjAyMS0xMi0wNlQwODowMTowMC40NjJaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIxMzQ0MzcxLyJdXX0="; private String objectName = "1344371/x1.txt"; //"yourAliyunId/" 开头 ; private String bucketName = "alicom-cardsms-resources"; private String endpoint = "https://example.aliyundoc.com"; private String localFilePath = "/Users/xxx/x.txt"; /** * 表单上传。 * * @throws Exception */ private void PostObject() throws Exception { // 设置表单Map。 Map<String, String> formFields = new LinkedHashMap<String, String>(); // 设置文件名称。 formFields.put("key", this.objectName); // 设置Content-Disposition。 formFields.put("Content-Disposition", "attachment;filename=" + localFilePath); // 如需回调,在表单Map中设置回调参数。 // setCallBack(formFields, callback); // 设置OSSAccessKeyId。 formFields.put("OSSAccessKeyId", accessKeyId); // 设置policy。 formFields.put("policy", policy); // 设置签名。 formFields.put("Signature", signature); String ret = formUpload(endpoint, formFields, localFilePath); System.out.println("Post Object [" + this.objectName + "] to bucket [" + bucketName + "]"); System.out.println("post reponse:" + ret); } private static String formUpload(String urlStr, Map<String, String> formFields, String localFile) throws Exception { String res = ""; HttpURLConnection conn = null; String boundary = "9431149156168"; try { URL url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5000); conn.setReadTimeout(30000); conn.setDoOutput(true); conn.setDoInput(true); conn.setRequestMethod("POST"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.*.*)"); // 如需设置MD5值。MD5值由整个body计算得出。 // conn.setRequestProperty("Content-MD5", "<yourContentMD5>"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); OutputStream out = new DataOutputStream(conn.getOutputStream()); // 遍历读取表单Map中的数据,将数据写入到输出流中。 if (formFields != null) { StringBuffer strBuf = new StringBuffer(); Iterator<Map.Entry<String, String>> iter = formFields.entrySet() .iterator(); int i = 0; while (iter.hasNext()) { Map.Entry<String, String> entry = iter.next(); String inputName = entry.getKey(); String inputValue = entry.getValue(); if (inputValue == null) { continue; } if (i == 0) { strBuf.append("--").append(boundary).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n"); strBuf.append(inputValue); } else { strBuf.append("\r\n").append("--").append(boundary).append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n"); strBuf.append(inputValue); } i++; } out.write(strBuf.toString().getBytes()); } // 读取文件信息,将要上传的文件写入到输出流中。 File file = new File(localFile); String filename = file.getName(); String contentType = new MimetypesFileTypeMap().getContentType(file); if (contentType == null || contentType.equals("")) { contentType = "application/octet-stream"; } StringBuffer strBuf = new StringBuffer(); strBuf.append("\r\n").append("--").append(boundary) .append("\r\n"); strBuf.append("Content-Disposition: form-data; name=\"file\"; " + "filename=\"" + filename + "\"\r\n"); strBuf.append("Content-Type: " + contentType + "\r\n\r\n"); out.write(strBuf.toString().getBytes()); DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); byte[] endData = ("\r\n--" + boundary + "--\r\n").getBytes(); out.write(endData); out.flush(); out.close(); // 读取返回数据。 strBuf = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { strBuf.append(line).append("\n"); } res = strBuf.toString(); reader.close(); reader = null; } catch (Exception e) { System.err.println("Send post request exception: " + e); throw e; } finally { if (conn != null) { conn.disconnect(); conn = null; } } return res; } public static void main(String[] args) throws Exception { OSSSample ossPostObject = new OSSSample(); ossPostObject.PostObject(); } }
修改OSS参数配置,数据来源于获取OSS上传信息GetOSSInfoForCardTemplate接口的调用结果,对应关系详见下表。
Java参数
对应OSS结果数据
示例
accessKeyId
Data.AccessKeyId
System.getenv("SCA_AK_ENV")
url
Data.Host
https://example.aliyundoc.com
policy
Data.Policy
eyJleHBpcmF0aW9uIjoiMjAyMS0wOS0xNlQwMzoyMjo1My44NjJaIiwiY29uZGl0aW9ucyI6W1siY29udGVudC1sZW5ndGgtcmFuZ2UiLDAsMTA0ODU3NjAwMF0sWyJzdGFydHMtd2l0aCIsIiRrZXkiLCIxMzQ0Mz****=
signature
Data.Signature
hK1BMsXZqCJvmnsZ98yG1b5****=
key
Data.StartPath+/
以StartPath开头后面添加/
示例:1344371/
bucket
Data.Bucket
alicom-cardsms-resources并非必要