位置: 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)

  • object.values()的用法(objectival)

    object.values()的用法(objectival)

  • 快手小店保证金怎么退(快手小店保证金根本退不了)

    快手小店保证金怎么退(快手小店保证金根本退不了)

  • 荣耀30pro是否支持应用分身呢(荣耀30pro是否支持红外遥控)

    荣耀30pro是否支持应用分身呢(荣耀30pro是否支持红外遥控)

  • 三星s10支持5g吗(三星s10+支持5g吗?)

    三星s10支持5g吗(三星s10+支持5g吗?)

  • 网络监测的方式(网络监测是什么样的工作)

    网络监测的方式(网络监测是什么样的工作)

  • 美团怎么看商家电话号码(美团怎么看商家月销量)

    美团怎么看商家电话号码(美团怎么看商家月销量)

  • 打10086能帮忙定位手机吗(打10086可以定位自己的手机号码吗)

    打10086能帮忙定位手机吗(打10086可以定位自己的手机号码吗)

  • 5g双模和5g全网通有什么区别(双模5g和全网通5g)

    5g双模和5g全网通有什么区别(双模5g和全网通5g)

  • 8p和8plus是同一款手机吗

    8p和8plus是同一款手机吗

  • 宽带los灯不亮正常吗(宽带猫los灯不亮是什么意思)

    宽带los灯不亮正常吗(宽带猫los灯不亮是什么意思)

  • vray渲染卡住不动(vray渲染突然变慢)

    vray渲染卡住不动(vray渲染突然变慢)

  • 6s和6sp的区别(苹果6s和6sp的区别)

    6s和6sp的区别(苹果6s和6sp的区别)

  • 候补购票失败退款多久到账(候补购票失败退钱吗)

    候补购票失败退款多久到账(候补购票失败退钱吗)

  • 苹果序列号12位含义(苹果序列号12位什么意思)

    苹果序列号12位含义(苹果序列号12位什么意思)

  • ipadmini是什么时候出的(ipadmini是什么时候发布的)

    ipadmini是什么时候出的(ipadmini是什么时候发布的)

  • microsoft可以删除吗(microsoft怎么删除多余的内容)

    microsoft可以删除吗(microsoft怎么删除多余的内容)

  • windows关闭窗口快捷键(windows关闭窗口的几种形式)

    windows关闭窗口快捷键(windows关闭窗口的几种形式)

  • n3350相当于什么处理器(n3540相当于)

    n3350相当于什么处理器(n3540相当于)

  • vivo手机怎么显示双卡(vivo手机怎么显示时间和日期)

    vivo手机怎么显示双卡(vivo手机怎么显示时间和日期)

  • 天猫违约金如何赔偿(给天猫的违约金怎么入账)

    天猫违约金如何赔偿(给天猫的违约金怎么入账)

  • 华为手环3如何接听电话(华为手环3如何充电)

    华为手环3如何接听电话(华为手环3如何充电)

  • wish接了一单怎么发货(wish没订单)

    wish接了一单怎么发货(wish没订单)

  • 怎么下载icloud上的照片到手机(怎么下载icloud上的备忘录)

    怎么下载icloud上的照片到手机(怎么下载icloud上的备忘录)

  • 去除oppo开发者模式通知(oppo手机开发者选项提示怎么关闭)

    去除oppo开发者模式通知(oppo手机开发者选项提示怎么关闭)

  • 解决TypeError: Cannot read properties of undefined (reading ‘NormalModule‘)的三种方案(解决的英文)

    解决TypeError: Cannot read properties of undefined (reading ‘NormalModule‘)的三种方案(解决的英文)

  • 基于Transformer的交通预测模型部分汇总【附源代码】(基于transformer的文本分类)

    基于Transformer的交通预测模型部分汇总【附源代码】(基于transformer的文本分类)

  • 【机器学习】支持向量回归

    【机器学习】支持向量回归

  • 收到退个税手续费要交增值税吗?
  • 收到个税返还手续费怎么算增值税附加
  • 先包装后销售
  • 计提税费表格
  • 公司老板有钱吗
  • 已经作为损失的资产以后纳税年度收回的会计处理
  • 企业不加入工会可以吗
  • 电子发票红字发票怎么开
  • 房地产企业会计制度
  • 房地产开发商转型
  • 会计录入凭证怎么录入
  • 税款返点如何做财务处理呢?
  • 一次性收到跨期租赁费会计分录
  • 购入债券计入什么科目
  • 出口退税操作明细表格
  • 转让无形资产所有权计入什么科目
  • 纳税主要是哪些方面
  • 收到多开的发票会计上怎么入成本?
  • 开票税额与申报税额差一分账务怎么处理
  • 土地契税税率怎么计算
  • 小规模开票软件服务费账务处理
  • 华为手机屏幕碎了照片
  • 腾讯手游助手好不好用
  • 支付职工培训费的现金流量项目
  • 清算资金往来借贷方什么意思
  • 房产税的会计科目怎么做
  • 零售环节的金银首饰需征收增值税吗
  • 借条怎么写有法律效力范本长期有效
  • 办理不动产证需要什么手续及证件
  • php中ajax
  • 直接计入所有者权益的交易或事项
  • 生产企业外销收入账务处理
  • 成本会计工作流程表
  • php实现登录功能
  • 前端 原生
  • thinkphp extend
  • viwer.js
  • javascript猜数字游戏+表单
  • vue2和vue3的区别大么
  • 利润分配和所有权的关系
  • 销项负数怎么报增值税
  • 汽车加油增值税专用发票
  • 工资发放用现金
  • 营改增后一般纳税人按简易办法计税的规定
  • 销售退回采购方的会计分录
  • 残疾人保障金为负数
  • 报废产品账务的处理方法
  • 一般餐饮业的固废是什么
  • 质量问题的扣款计入什么科目
  • 参加新冠疫情防控工作总结
  • 建筑行业怎么确认收入
  • 清理固定资产的税费
  • 厂商租赁公司
  • 收到保险赔款是什么意思
  • 公司基本户的钱怎么用
  • 长期应付款涉及哪些业务,应如何进行核算
  • SQL 导入导出Excel数据的语句
  • windows无法启动怎么解决
  • windows time同步系统时间的服务无法启动报错1058解决方法
  • WIN10系统如何修复
  • win10正式版多少钱
  • w7开机界面
  • cmd运行指令闪黑框
  • Android多线程开发
  • javax.net.ssl.SSLException: hostname in certificate didn't match:
  • shell函数返回多个值包含数组
  • 骨骼动画spine
  • 安卓手机管家怎么关闭
  • 异步promise原理
  • javascript学到什么程度
  • python设计二叉树结构
  • 在python中的用法
  • python中jsonpath
  • python中chr(ord())
  • mixed模型
  • 重庆市税收排名地区
  • 深圳市国家税务局赵雨婷
  • 怎么在开票系统导出开票明细
  • 荆州市税务局现任名单
  • 逆光代售和神仙代售那个好一点
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设