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

  • 互联网时代,让用户来帮助你建设和宣传品牌(互联网时代让生活更加美好)

    互联网时代,让用户来帮助你建设和宣传品牌(互联网时代让生活更加美好)

  • b站身份证能换绑吗(b站身份证换绑网站)

    b站身份证能换绑吗(b站身份证换绑网站)

  • 微信发的消息删除了对方可以看到吗(微信发的消息删除后自己还能看到吗)

    微信发的消息删除了对方可以看到吗(微信发的消息删除后自己还能看到吗)

  • 爱情树退出后会通知对方吗(爱情树退出了怎么还原)

    爱情树退出后会通知对方吗(爱情树退出了怎么还原)

  • oppor17电量耐用吗(oppor17电池电量不抗用了)

    oppor17电量耐用吗(oppor17电池电量不抗用了)

  • 淘宝一月一号有活动吗(淘宝一月一号有优惠吗)

    淘宝一月一号有活动吗(淘宝一月一号有优惠吗)

  • 快充手机充一晚上对手机有影响吗(快充手机充一晚上)

    快充手机充一晚上对手机有影响吗(快充手机充一晚上)

  • 怪兽充电宝几小时封顶(怪兽充电宝小程序)

    怪兽充电宝几小时封顶(怪兽充电宝小程序)

  • 视频聊天软件平台都有哪些(视频聊聊软件)

    视频聊天软件平台都有哪些(视频聊聊软件)

  • oppo连不上苹果11热点(oppo手机连不上iphone11的热点)

    oppo连不上苹果11热点(oppo手机连不上iphone11的热点)

  • 华为如何自由复制文字(华为复制功能怎么用)

    华为如何自由复制文字(华为复制功能怎么用)

  • 手机monster模式什么意思(手机monster模式有什么用)

    手机monster模式什么意思(手机monster模式有什么用)

  • 苹果耳机有一只总没电(苹果耳机有一只不响)

    苹果耳机有一只总没电(苹果耳机有一只不响)

  • cad多大内存(cad占用内存多大)

    cad多大内存(cad占用内存多大)

  • iphonexsmax怎么清除用过的程序(iPhonexsmax怎么清理内存)

    iphonexsmax怎么清除用过的程序(iPhonexsmax怎么清理内存)

  • 电脑上为啥老是有敲击声(电脑为啥老是蓝屏重启)

    电脑上为啥老是有敲击声(电脑为啥老是蓝屏重启)

  • 荣耀30pro可以贴钢化膜吗(荣耀30pro可以贴膜吗)

    荣耀30pro可以贴钢化膜吗(荣耀30pro可以贴膜吗)

  • 苹果8微信分身怎么弄(苹果8微信分身在哪里)

    苹果8微信分身怎么弄(苹果8微信分身在哪里)

  • qq显示wifi在线是什么意思(qq显示wifi在线说明什么)

    qq显示wifi在线是什么意思(qq显示wifi在线说明什么)

  • 计算器上off是什么键(计算器上off是什么功能键)

    计算器上off是什么键(计算器上off是什么功能键)

  • 抖音照片上的字怎么写上去的(抖音照片上的字怎么慢慢出来)

    抖音照片上的字怎么写上去的(抖音照片上的字怎么慢慢出来)

  • 我国面积最大的省(我国面积最大的省份)

    我国面积最大的省(我国面积最大的省份)

  • 微信群太多怎么退(微信群太多怎么找出来)

    微信群太多怎么退(微信群太多怎么找出来)

  • 荣耀v20怎么看后台运行(荣耀v20手机型号怎么看)

    荣耀v20怎么看后台运行(荣耀v20手机型号怎么看)

  • wo27s光纤猫是千兆吗(光纤猫是千兆的吗)

    wo27s光纤猫是千兆吗(光纤猫是千兆的吗)

  • 小米蓝牙耳机可以连接华为手机吗(小米蓝牙耳机可以连接OPPO手机吗)

    小米蓝牙耳机可以连接华为手机吗(小米蓝牙耳机可以连接OPPO手机吗)

  • 电脑文件夹怎么发送给别人(电脑文件夹怎么删除)

    电脑文件夹怎么发送给别人(电脑文件夹怎么删除)

  • 怎么关闭qq小程序功能(怎么关闭qq小程序游戏功能)

    怎么关闭qq小程序功能(怎么关闭qq小程序游戏功能)

  • Win11应用商店上架 Windows Linux 子系统(WSL):程序升级更快,无需升级操作系统(win11 应用商店)

    Win11应用商店上架 Windows Linux 子系统(WSL):程序升级更快,无需升级操作系统(win11 应用商店)

  • 关于美容院的会计如何做账
  • 一般纳税人账务核算不健全如何税务处理
  • 预付的成本票计入什么科目?
  • 个税申报信息怎么恢复
  • 公司给员工报销话费怎么做账
  • 自产自销发票可以抵扣增值税发票吗
  • 购买空调的报销单怎么写
  • 开具简易计税房租发票怎样填写增值税申报表
  • 银行电子回单号码什么意思
  • 原材料做成库存会计分录
  • 一般纳税人贸易公司每个月最低费用多少
  • 税率16降到13什么时候实施
  • 未计提工资
  • 在会计上其他业务是什么
  • 停车场领的定额发票要怎么报税?
  • 汇算清缴专项附加扣除去年忘记填的能补填吗?
  • 有关于秋天的诗句
  • 收到厂家返利怎么做分录
  • 公司收到拆迁补偿款要交税吗
  • 第三方支付销售
  • php数组函数,选班长
  • linux grep显示行数
  • windows7怎样升级windows10
  • Linux系统中quota磁盘命令的相关使用解析
  • 购买增值税税控系统专用设备账务处理
  • 什么叫奖励旅游
  • 怎么解锁城堡上空
  • 企业租赁发票税率是多少2023年
  • 扣缴义务人应扣未扣如何处罚
  • 资产为什么等于成本
  • php-xml
  • “php”
  • 暂估收入如何做账
  • 长期股权投资的账务处理
  • 话费补贴算工资还是福利
  • 人工安装费是几个点税税率
  • 发票报销有时间期限吗
  • 所得税费用影响企业营业利润吗
  • 人工智能自动对焦又叫什么
  • 弥补以前年度亏损后怎么交所得税
  • 会计账簿错误处理方式
  • 什么叫代销合同
  • 偿债基金专户
  • 企业所得税审计调整分录
  • 企业大股东减持股权
  • 损益类账户借贷方向增减
  • 主营业务收入用什么账簿登记
  • 水利建设基金一直没缴纳
  • 什么叫系统服务
  • 固定资产处置有净值怎么处理
  • 建筑企业工程施工科目怎么结转
  • 固定资产明细账范本
  • 委托加工的成本如何核算
  • sqlserver1053怎么解决
  • 分类不同
  • Centos MySQL 5.7安装、升级教程
  • windows 10 build 9888
  • win7旗舰版系统还原无法启动
  • windows8蓝牙设置在哪里
  • xp系统如何更新
  • win8系统蓝屏后无法修复
  • win8怎么关闭系统自动更新
  • windows7如何取消锁屏密码
  • win8系统怎么打开运行
  • Android通过HttpURLConnection获取JSON并进行UI更新
  • [置顶]bilinovel
  • json对象如何取值
  • unity3d性能优化之贴图科普篇
  • jQuery prototype冲突的2种解决方法(附demo示例下载)
  • 深入理解新发展理念,推进供给侧结构性改革心得体会
  • unity教程完整版
  • 陕西省税务局电子税务局官网
  • 河北市国家税务局官网
  • 每月个人所得税申报截止时间是几号
  • 城镇土地使用税按月还是按年交
  • 最多跑一次改革是谁提出来的
  • 国家税务总局并入财政部最新消息
  • 内蒙古国家税务总局官网
  • 代账好做吗
  • 契税维修基金交给谁
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设