位置: IT常识 - 正文

前端直传阿里云OSS(阿里前端做什么)

编辑:rootadmin
前端直传阿里云OSS

推荐整理分享前端直传阿里云OSS(阿里前端做什么),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:前端直传阿里云怎么用,前端直传阿里云怎么用,阿里云前端面试题,阿里云前端外包怎么样,前端项目部署到阿里云服务器,前端直传阿里云怎么用,前端直传阿里云怎么用,前端直传阿里云怎么用,内容如对您有帮助,希望把文章链接给更多的朋友!

阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。

目前通过Web端直传文件(Object)到OSS,有两种方案:

一、利用OSS Browser.js SDK将文件上传到OSS。该方案通过OSS Browser.js SDK直传数据到OSS,支持断点续传,支持各种主流浏览器,可以将File对象、Blob数据以及OSS Buffer上传OSS,该方案还支持下载和删除

二、利用OSS提供的PostObject接口来实现表单上传,不支持断点续传,支持h5,小程序,支持uniapp的uni.uploadFile接口

方案一:使用阿里云SDK上传

由于前端环境不安全,为避免暴露阿里云账号访问密钥(AccessKey ID和AccessKey Secret),该方案需要搭建STS服务获取临时访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken),需要先开通STS服务,参考官方文档

后端

后端需要导入aliyun-sdk-oss包,用于获取前端需要的key和secret

JDK版本:jdk8

<dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>2.0.7</version> <!--<version>3.15.0</version>最新--></dependency>

如果是java9及以上版本,则需要添加jaxb相关依赖。添加jaxb相关依赖示例代码如下:

<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version></dependency><dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version></dependency><!-- no more than 2.3.3--><dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.3</version></dependency>

搭建STS服务(部分代码)

// STS接入地址,例如sts.cn-hangzhou.aliyuncs.com。 @Value("${ramEndpoint}") private String ramEndpoint; // 访问密钥AccessKey ID和AccessKey Secret @Value("${ramAccessKeyId}") private String ramAccessKeyId; @Value("${ramAccessKeySecret}") private String ramAccessKeySecret; // 角色ARN @Value("${ramRoleArn}") // 自定义角色会话名称,用来区分不同的令牌,例如可填写为SessionTest private String ramRoleArn; @Value("${ramRoleSessionName}") private String ramRoleSessionName; private Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired RedisTemplate redisTemplate; /** * 通过RAM子账号获取stsToken,作为临时凭据 */ @RequestMapping(value = "getStsToken", method = {RequestMethod.GET, RequestMethod.POST}) public Object getStsToken() { ResponseVo responseVo = new ResponseVo(); AssumeRoleResponse response = null; Object redisToken = null; try { redisToken = redisTemplate.opsForValue().get("stsToken"); } catch (Exception e) { logger.error(e.getMessage()); responseVo.setError(GlobalErrorCode.SYS_RUN_ERROR.getCode()); return responseVo; } if (redisToken != null) { response = JSONObject.parseObject(redisToken.toString(), AssumeRoleResponse.class); responseVo.setSuccess(response); return responseVo; } else { String policy = "{\n" + " \"Version\": \"1\", \n" + " \"Statement\": [\n" + " {\n" + " \"Action\": [\n" + " \"oss:*\"\n" + " ], \n" + " \"Resource\": [\n" + " \"acs:oss:*:*:*\" \n" + " ], \n" + " \"Effect\": \"Allow\"\n" + " }\n" + " ]\n" + "}"; try { DefaultProfile.addEndpoint("", "", "Sts", ramEndpoint); // 构造default profile(参数留空,无需添加region ID) IClientProfile profile = DefaultProfile.getProfile("", ramAccessKeyId, ramAccessKeySecret); // 用profile构造client DefaultAcsClient client = new DefaultAcsClient(profile); final AssumeRoleRequest request = new AssumeRoleRequest(); request.setMethod(MethodType.POST); request.setRoleArn(ramRoleArn); request.setRoleSessionName(ramRoleSessionName); request.setPolicy(policy); // 若policy为空,则用户将获得该角色下所有权限 request.setDurationSeconds(20 * 60L); // 设置凭证有效时间,单位秒 //获取凭证 response = client.getAcsResponse(request); /* * 缓存该凭证,凭证失效后才从OSS再次获取凭证 * 凭证有效时间为20分钟,Redis里只缓存10分钟 */ redisTemplate.opsForValue().set("stsToken", JSONObject.toJSONString(response), 10 * 60, TimeUnit.SECONDS); responseVo.setSuccess(response); return responseVo; } catch (ClientException e) { logger.error(e.getErrMsg()); responseVo.setError(GlobalErrorCode.SYS_RUN_ERROR.getCode()); return responseVo; } } }

参考阿里云文档

前端

安装

$ npm install ali-oss --save

部分代码

onLoad() {this.getStsToken()},前端直传阿里云OSS(阿里前端做什么)

methods

/*** @param {String} pathAndName Object完整路径。Object完整路径中不能包含Bucket名称("exampledir/exampleobject.txt")* @param {Object} data (file对象、Blob数据或者OSS Buffer)*/async putObject(pathAndName, data) { try { // 您可以通过自定义文件名(例如exampleobject.txt)或文件完整路径(例如exampledir/exampleobject.txt)的形式实现将数据上传到当前Bucket或Bucket中的指定目录。 const result = await this.getClient().put( pathAndName, data ); console.log('result:', result); } catch (e) { console.log(e); }}, getClient() { if (this.client) { return this.client } const OSS = require('ali-oss'); const client = new OSS({ // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: 'oss-cn-qingdao', // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。 accessKeyId: this.stsToken.credentials.accessKeyId, accessKeySecret: this.stsToken.credentials.accessKeySecret, // 从STS服务获取的安全令牌(SecurityToken)。 stsToken: this.stsToken.credentials.securityToken, refreshSTSToken: async () => { // 向您搭建的STS服务获取临时访问凭证。 let info = await this.$post(GET_STS_TOKEN) info = info.data console.log('-----------refresh--token') return { accessKeyId: info.credentials.accessKeyId, accessKeySecret: info.credentials.accessKeySecret, stsToken: info.credentials.securityToken } }, // 刷新临时访问凭证的时间间隔,单位为毫秒。每隔一段时间定时器会自动掉后台接口刷新token refreshSTSTokenInterval: 600000, // 填写Bucket名称。 bucket: 'zxxxxth-bucket' }); this.client = client return this.client }, getStsToken() { //从后台获取stsToken(改成自己的前端请求接口) this.$post(GET_STS_TOKEN).then(rsp => { if (rsp.success) { this.stsToken = rsp.data; // 初始化一下client让定时任务启动,自动刷新token(避免过期) this.getClient() console.log('this.stsToken:', this.stsToken) } else { uni.showToast({ title: rsp.message, duration: 2000 }); } }) },

refreshSTSToken参数说明:当初始化new OSS()时,定时器会启动,当时间到了refreshSTSTokenInterval所设置的值时,并不会立即调用后台接口获取token,只有手动触发put()接口时,才会调用后台接口获取token

参考阿里云文档

开通STS服务步骤

方案二:使用PostObject接口来实现表单上传

这个方案支持小程序上传,uniapp上传。无需开通STS服务

后端

获取postObject接口需要的policy,OSSAccessKeyId,signature 参考官方文档

这里签名使用后端签名,所以不需要申请开通STS服务

简化版,无回调/** * 利用OSS提供的PostObject接口,通过表单上传的方式将文件上传到OSS。 * 该方案兼容大部分浏览器,但在网络状况不好的时候,如果单个文件上传失败, * 只能重试上传。上传的Object大小不能超过5 GB。 * @return ResponseVo{success:true,message:'',data:{},code:200} */ @RequestMapping(value = "getPostObjectParams", method = {RequestMethod.GET, RequestMethod.POST}) public Object getPostObjectParams() { ResponseVo responseVo = new ResponseVo(); responseVo.setSuccess(OSSServer.getPostObjectParams()); return responseVo; }

OSSServer.class

public static OSSClient getOSSClient() {if (null == ossClient) {ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);}return ossClient;}/** * 获取表单上传的方式的PostObject参数 * @return */public static Map<String, Object> getPostObjectParams() {Map<String, Object> respMap = new LinkedHashMap();// 限制参数的生效时间,单位为分钟,默认值为20。int expireTime = 20;// 限制上传文件的大小,单位为MB,默认值为100。int maxSize = 100;// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。// 如果值为"test"那么前端的key参数必须以"test"开头,如test/*、test1.jpg、test/comment/11.jpgString dir = "";// 创建OSSClient实例。OSS ossClient = getOSSClient();try {long expireEndTime = System.currentTimeMillis() + expireTime * 1000 * 60;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize * 1024 * 1024);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);respMap.put("accessKeyId", accessKeyId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("expire", expireEndTime / 1000);} catch (Exception e) {log.error("getPostObjectParams", e);}return respMap;}

大多数情况下,用户上传文件后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,为此OSS提供了上传回调方案。

流程图:

当用户要上传一个文件到OSS,而且希望将上传的结果返回给应用服务器时,需要设置一个回调函数,将请求告知应用服务器。用户上传完文件后,不会直接得到返回结果,而是先通知应用服务器,再把结果转达给用户。

有回调的PostObject参数/** * 获取表单上传的方式的PostObject参数【有回调】 * @return */public static Map<String, Object> getPostObjectParams() {Map<String, Object> respMap = new LinkedHashMap();// 限制参数的生效时间,单位为分钟,默认值为20。int expireTime = 20;// 限制上传文件的大小,单位为MB,默认值为10。int maxSize = 10;// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。// 如果值为"test"那么前端的key参数必须以"test"开头,如test/*、test1.jpg、test/comment/11.jpg// 可以让用户没有办法上传到其他的目录,从而保证了数据的安全性String dir = "";// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。String callbackUrl = "https://jmt.xxx.cn/common/postObjectCallBack/";// 创建OSSClient实例。OSS ossClient = getOSSClient();try {long expireEndTime = System.currentTimeMillis() + expireTime * 1000 * 60;Date expiration = new Date(expireEndTime);PolicyConditions policyConds = new PolicyConditions();policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize * 1024 * 1024);policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);byte[] binaryData = postPolicy.getBytes("utf-8");String encodedPolicy = BinaryUtil.toBase64String(binaryData);String postSignature = ossClient.calculatePostSignature(postPolicy);respMap.put("accessKeyId", accessKeyId);respMap.put("policy", encodedPolicy);respMap.put("signature", postSignature);respMap.put("expire", expireEndTime / 1000);// 配置回调地址JSONObject jasonCallback = new JSONObject();jasonCallback.put("callbackUrl", callbackUrl);//jasonCallback.put("callbackBody",//"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");jasonCallback.put("callbackBody", "{\"filename\":${object},\"mimeType\":${mimeType}}");jasonCallback.put("callbackBodyType", "application/json");//application/x-www-form-urlencodedString base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());respMap.put("callback", base64CallbackBody);} catch (Exception e) {log.error("getPostObjectParams", e);}return respMap;}给oss回调的接口 @RequestMapping(value = "postObjectCallBack", method = RequestMethod.POST) public Object postObjectCallBack(HttpServletRequest request, @RequestBody Object callbackBody) throws IOException { log.info("---callbackBody={}",callbackBody);// "{"filename":"test/comment/tt1.jpg","mimeType":"image/png"}" return callbackBody; }前端小程序const host = '<host>'; //"https://examplebucket.oss-cn-hangzhou.aliyuncs.com"const signature = '<signatureString>';const ossAccessKeyId = '<accessKey>';const policy = '<policyBase64Str>';const key = '<object name>';const securityToken = '<x-oss-security-token>'; const filePath = '<filePath>'; // 待上传文件的文件路径。wx.uploadFile({ url: host, // 这个是阿里云bucket的根地址,使用这个地址拼接路径可以访问已上传的文件。如果是自己服务器则是开发者服务器的URL。 filePath: filePath,// 本地文件路径,小程序chooseImage方法返回的路径 name: 'file', // 必须填file。 formData: { key, policy, OSSAccessKeyId: ossAccessKeyId, signature, // 'x-oss-security-token': securityToken // 使用STS签名时必传。 }, success: (res) => { if (res.statusCode === 204) { console.log('上传成功'); } }, fail: err => { console.log(err); }});uniapp、uView的Upload组件uni.uploadFile({ url: 'https://res.xxx.cn', //这个是阿里云bucket的根地址,使用这个地址拼接路径可以访问已上传的文件 filePath: url,// 本地文件路径,小程序chooseImage方法返回的路径 name: 'file',// 必须填file formData: { key: 'test/comment/tt1.jpg',//会把tt1.jpg图片上传至bucket(上方url所指向)的test/comment目录 policy: this.postObject.policy, OSSAccessKeyId: this.postObject.accessKeyId, signature: this.postObject.signature, // callback: this.postObject.callback }, success: (res) => { console.log('uni.uploadFile success:', res) if(res.statusCode===204){ // 上传成功 console.log('-------------success------------') }else if(res.statusCode===403){ // Policy expired. uni.showToast({ title: '网络超时', duration: 2000 }); // 续期 this.getPostObjectParams() }else{ console.log('上传失败') } // setTimeout(() => { resolve(res) // }, 1000) }, fail(err) { console.error('uni.uploadFile: fail', err) }});onLoad() {this.getPostObjectParams()},...........getPostObjectParams() { //从后台获取stsToken this.$post(GET_POST_OBJECT_PARAMS).then(rsp => { if (rsp.success) { this.postObject = rsp.data; console.log('this.postObject:', this.postObject) } else { uni.showToast({ title: rsp.message, duration: 2000, icon:'none' }); } })},

参考官方文档

举一个uniapp例子

UI库:uView

<template><!-- 发表评论 --><view class="create-comment"><view class="star comment-common"><view class="title">评分</view><view class="control"><text class="name">游玩体验</text><u-rate :count="5" v-model="starCount" :touchable="false" active-color="#E65526" size="24"></u-rate></view></view><view class="content comment-common"><view class="title">评价内容</view><textarea v-model="resourceComment.content" maxlength="200"placeholder="游玩的满意吗?大家都想了解这里值得去吗?有什么亮点?期待你精彩的点评!"></textarea></view><view class="picture comment-common"><view class="title">图片</view><!-- name=1对应fileList1 --><u-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple :maxCount="15":maxSize="maxSize"></u-upload></view><view class="picture comment-common"><view class="title">视频</view><!-- name=2对应fileList2 --><u-upload :fileList="fileList2" @afterRead="afterRead" @delete="deletePic" name="2" multiple :maxCount="1":maxSize="maxSize" accept="video" uploadIcon="movie"></u-upload></view><button @click="submit()" type="warn" class="submit" :loading="loading" :disabled="loading">发布</button></view></template><script>import {GET_POST_OBJECT_PARAMS} from '../../api/api.js'export default {data() {return {starCount: 0,resourceComment: {content: ''},fileList1: [],fileList2: [],loading: false,postObject: {expire: 0},maxSize: 100 * 1024 * 1024}},onLoad() {},methods: {// -----upload start// 新增图片async afterRead(event) {console.log('event:', event)// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式let lists = [].concat(event.file)// console.log('lists:', lists)let fileListLen = this[`fileList${event.name}`].length// console.log('fileListLen:', fileListLen)lists.map((item) => {this[`fileList${event.name}`].push({...item,status: 'uploading',message: '上传中'})})let time = new Date().getTime() / 1000// console.log('time:', time)if (time > this.postObject.expire) {// policy过期,续期await this.getPostObjectParams()}for (let i = 0; i < lists.length; i++) {const result = await this.uploadFilePromise(lists[i].url)let item = this[`fileList${event.name}`][fileListLen]this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {status: result ? 'success' : 'failed',message: '',url: result}))fileListLen++}},compressJpgImage(src) {return new Promise((resolve, reject) => {// uni.compressImage({// src: src,// quality: 80,// success: res => {// console.log(res.tempFilePath)// }// })})},uploadFilePromise(url) {return new Promise((resolve, reject) => {let a = uni.uploadFile({url: 'https://res.xxxx.cn',filePath: url,name: 'file', // 必须填fileformData: {key: 'test/comment/tt3.jpg',policy: this.postObject.policy,OSSAccessKeyId: this.postObject.accessKeyId,signature: this.postObject.signature,callback: this.postObject.callback},success: (res) => {// 未配置回调 上传成功返回 {date:"",errMsg:"uploadFile:ok",statusCode:204},如果配置了回调data参数才会有值// 配置了回调 上传成功返回 {{data:{"filename":"test/comment/tt1.jpg","mimeType":"image/png"},errMsg:"uploadFile:ok",statusCode:200}console.log('uni.uploadFile success():', res)if (res.statusCode === 204 || res.statusCode === 200) {// 上传成功console.log('-------------uploaded success')resolve(url)} else {console.log('-------------uploaded failed')uni.showToast({title: '上传失败',duration: 2000,icon: 'error'});resolve()}},fail(err) {console.error('uni.uploadFile: fail():', err)}});})},// 删除图片deletePic(event) {this[`fileList${event.name}`].splice(event.index, 1)},// -----upload endgetPostObjectParams() {//从后台获取postObjectreturn this.$post(GET_POST_OBJECT_PARAMS,{folderType:'comment'}).then(rsp => {// this.postObject = rspif (rsp.success) {this.postObject = rsp.data;console.log('this.postObject:', this.postObject)} else {console.error('getPostObjectParams:', rsp.message || '系统错误')}})}}}</script><style lang="scss">.create-comment {padding: 12px;.comment-common {margin-bottom: 10px;padding: 15px 10px;background-color: white;border-radius: 10px;}.title {margin-bottom: 10px;font-size: 16px;font-weight: bold;}.star {.control {display: flex;align-items: center;.name {margin-right: 10px;}}}.content {textarea {font-size: 14px;width: 100%;}}.picture {}.submit {margin-top: 20px;width: 80%;font-size: 15px;color: white;background-color: #e65526;}}</style>

附:根据blob链接获取blob对象

/** * 根据blob链接获取blob对象 * @param {Object} url "blob:http://localhost:8085/d688ce4f-0f5d-418c-85ad-62bcb3f38dee" * @returns Blob(31846) {size: 31846, type: "image/jpeg"} */getBlobByUrl(url) {return uni.request({url: url,// 合法值:text、arraybufferresponseType: 'arraybuffer'}).then(data=>{const [error, rsp] = data;if(error){console.error(`post-error:${error}, url:${url}`)return {message: error.errMsg}}else{let buffer = rsp.data// ArrayBuffer(185) {}console.log('buffer:', buffer)return new Blob([buffer])}})// return new Promise((resolve, reject) => {// let xhr = new XMLHttpRequest()// xhr.open('GET', url, true)// xhr.responseType = 'blob'// xhr.onload = function(e) {// if (this.status == 200) {// let myBlob = this.response// // let file = new window.File(// // [myBlob],// // 'myfile.jpg', {// // type: myBlob.type// // }// // )// // console.log("files:", file)// resolve(myBlob)// } else {// reject(false)// }// }// xhr.send()// })},

blobUrl、blob、base64、file相互转化:https://www.cnblogs.com/jing-zhe/p/15402775.html

uniapp选择file

<button @click="submit()" type="warn" class="submit" :loading="loading" :disabled="loading">发布</button>submit() { let utils = new Utils() uni.chooseImage({ count: 6, //默认9 sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有 sourceType: ['album'], //从相册选择 success: function(res) { console.log(JSON.stringify(res.tempFilePaths)); console.log(res.tempFiles) utils.getFileMD5(res.tempFiles[0], function(md5) { console.log('md5:', md5) }) } });},
本文链接地址:https://www.jiuchutong.com/zhishi/290191.html 转载请保留说明!

上一篇:鸟瞰蒙特雷附近的大苏尔海岸线,加利福尼亚州 (© Blue Planet Archive/Alamy)(蒙特雷景点)

下一篇:小刺猬 (© lorenzo104/Getty Images)

  • 苹果13怎么恢复出厂设置(苹果13怎么恢复短信删除的内容)

    苹果13怎么恢复出厂设置(苹果13怎么恢复短信删除的内容)

  • 小米手机高清通话在哪里设置(小米手机高清通话怎么打开设置)

    小米手机高清通话在哪里设置(小米手机高清通话怎么打开设置)

  • qq音乐音乐人怎么认证(qq音乐人怎么)

    qq音乐音乐人怎么认证(qq音乐人怎么)

  • iQOO Neo5使用的是什么散热技术(iqoo neo5都有什么功能)

    iQOO Neo5使用的是什么散热技术(iqoo neo5都有什么功能)

  • 苹果手机如何截图(苹果手机如何截取视频中的一段视频)

    苹果手机如何截图(苹果手机如何截取视频中的一段视频)

  • iphone x开机停留在苹果标志(iphone x停留在开机logo画面)

    iphone x开机停留在苹果标志(iphone x停留在开机logo画面)

  • vivo手机发烫电量消耗快是什么原因(vivo手机发烫电量消耗快什么原因)

    vivo手机发烫电量消耗快是什么原因(vivo手机发烫电量消耗快什么原因)

  • 网络机顶盒什么网络都可以用吗(网络机顶盒什么时候出现的)

    网络机顶盒什么网络都可以用吗(网络机顶盒什么时候出现的)

  • 手机信号耗电量非常大是什么问题(手机信号耗电量最高 小米)

    手机信号耗电量非常大是什么问题(手机信号耗电量最高 小米)

  • q8200相当于i几(q8200相当于什么水平)

    q8200相当于i几(q8200相当于什么水平)

  • 显卡需要换硅脂吗(笔记本怎么换硅脂)

    显卡需要换硅脂吗(笔记本怎么换硅脂)

  • qq相册照片还原清晰度(qq相册还原后去哪儿了)

    qq相册照片还原清晰度(qq相册还原后去哪儿了)

  • 手机微信怎么看黑名单在哪里(手机微信怎么看电脑有没有登录)

    手机微信怎么看黑名单在哪里(手机微信怎么看电脑有没有登录)

  • 7.9寸ipad长宽多少厘米(ipad9.7寸的长宽)

    7.9寸ipad长宽多少厘米(ipad9.7寸的长宽)

  • word页面设置在哪(word页面设置在哪个菜单栏)

    word页面设置在哪(word页面设置在哪个菜单栏)

  • 华为设置上滑返回(华为怎么设置往上滑返回键)

    华为设置上滑返回(华为怎么设置往上滑返回键)

  • xs前置摄像头像素(xs前置摄像头模糊怎么办)

    xs前置摄像头像素(xs前置摄像头模糊怎么办)

  • 快手小店服务费是多少(快手小店服务费收取标准)

    快手小店服务费是多少(快手小店服务费收取标准)

  • freebud和flypods有啥区别(flypods和freebuds3i)

    freebud和flypods有啥区别(flypods和freebuds3i)

  • apple id不在激活状态怎么弄(appid显示不在激活状态)

    apple id不在激活状态怎么弄(appid显示不在激活状态)

  • 苹果x和xs一样大吗(苹果x和苹果xs有什么区别)

    苹果x和xs一样大吗(苹果x和苹果xs有什么区别)

  • 帝国cms怎么增加专题(帝国cms怎么增加子栏目)

    帝国cms怎么增加专题(帝国cms怎么增加子栏目)

  • python中next函数如何使用?(python next iter)

    python中next函数如何使用?(python next iter)

  • 企业签订技术培训合同是否需要缴纳印花税?
  • 车船税是否每年都交
  • 生产企业出口货物劳务免抵退税申报明细表
  • 累计折旧贷方余额表示
  • 员工工资占公司收入比例怎么算
  • 公司员工社保怎么办理的
  • 飞机票的快递费多少钱
  • 即将发生坏事的预兆
  • 个体工商户出租商铺个人所得税
  • 企业减免的所得税税率
  • 税收和税法是什么关系
  • 应收账款已收回但是账面还有余额怎么处理
  • 地质勘察费用应由谁支付
  • 公司厂房出租发票怎么开
  • 房地产开发企业土地增值税清算
  • 关于财产保险公司的论文
  • 销售坚果税率多少
  • 代扣大额医保进哪个账户
  • 确认坏账损失的分录怎么做
  • 生产企业出口退税申报系统详细操作流程
  • 银行贷款入公账怎么入分录?
  • 变更股权需要资质证书吗
  • basic run
  • 股东投入的资金可以退回吗
  • 增值税红字发票开具
  • 苹果电脑设置壁纸为什么重启就没了
  • 开启自动备份注册表
  • php加密解密函数高级
  • 处理固定资产的账务处理
  • 股东退股怎么分钱
  • 以前年度损益调整
  • 法人从公账上取款会计分录
  • 全面带你了解AIGC的风口
  • 微信小程序开发者工具
  • 增值税折扣发票有折扣字样
  • 基本生产成本和辅助生产成本区别
  • 物业公司属于生活性服务业吗
  • 主营业务税金及附加包括增值税吗
  • 企业的留存收益有
  • 用友t3资产负债表怎么生成季报
  • 收到退还的增值税
  • 建筑工程企业人才优势怎么写
  • 定期定额征收和核定征收哪个好
  • 研发支出的费用化支出计入
  • 金税三期有什么用
  • 实收资本增减变化为负数的原因
  • 付设备款的会计分录
  • 招待费发票怎么做分录
  • 流动负债占比低什么意思
  • 怎么取最大值函数
  • 视同销售但未收到钱怎么做账?
  • 免征增值税进项税额不得抵扣
  • 年终建账于年初建账,在录入期初余额时有什么不一样?
  • 主营业务收入的英文
  • 非营利组织会计科目账务处理
  • 会计凭证发票粘贴
  • 如何设置物资采集系统
  • 电脑显示配置windows
  • 怎么提升命令提示符
  • solaris配置ip地址
  • windows没网络是怎么回事
  • macbookpro怎么测声音
  • linux系统bug
  • centos6.5忘记密码
  • windows7开机显示错误恢复进不去
  • linux 用户进程
  • 没有协议盒可以设置协议吗
  • android studio 新建项目只有.idea文件
  • ansi std
  • nodejs xhr
  • python颜色表
  • js的实现原理
  • 全屏沉浸式
  • jquery表格隔行变色代码
  • 土地增值额未超过20%
  • 东莞市电子税务局app
  • 国税局宁夏税务
  • 新加坡国税局的电话号码
  • 补缴往年土地使用税怎么做分录
  • 推动税务系统全面从严
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设