com-upload-oss.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <template id="com-upload-oss">
  2. <div class="com-upload-oss" @click="handleClick">
  3. <slot></slot>
  4. <!-- 文件格式&是否支持多文件上传 -->
  5. <input ref="input" type="file" :accept="accept" :multiple="multiple" style="display: none"
  6. @change="handleChange">
  7. </div>
  8. </template>
  9. <script type="text/javascript" src="/resources/js/cos-js-sdk-v5.min.js"></script>
  10. <script type="text/javascript" src="/resources/js/aliyun-oss-sdk.min.js"></script>
  11. <script type="text/javascript" src="/resources/js/qiniu.min.js"></script>
  12. <script>
  13. Vue.component('com-upload-oss', {
  14. template: '#com-upload-oss',
  15. props: {
  16. disabled: Boolean,
  17. multiple: Boolean,
  18. max: Number,
  19. accept: String,
  20. params: Object,
  21. fields: Object,
  22. config: Object,
  23. },
  24. data() {
  25. return {
  26. dialogVisible: false,
  27. loading: true,
  28. attachments: [],
  29. checkedAttachments: [],
  30. files: [],
  31. };
  32. },
  33. computed: {
  34. videoConfigInfo() {
  35. return this.config
  36. },
  37. uploadParams() {
  38. return this.params
  39. }
  40. },
  41. created() {},
  42. methods: {
  43. handleClick() {
  44. if (this.disabled) {
  45. return;
  46. }
  47. this.$refs.input.value = null;
  48. this.$refs.input.click();
  49. },
  50. handleChange(e) {
  51. if (!e.target.files) return;
  52. this.uploadFiles(e.target.files);
  53. },
  54. uploadFiles(rawFiles) {
  55. if (this.max && rawFiles.length > this.max) {
  56. this.$message.error('最多一次只能上传' + this.max + '个文件。')
  57. return;
  58. }
  59. this.files = [];
  60. for (let i = 0; i < rawFiles.length; i++) {
  61. const file = {
  62. _complete: false,
  63. response: null,
  64. rawFile: rawFiles[i],
  65. };
  66. this.files.push(file);
  67. }
  68. this.$emit('start', this.files);
  69. // 循环上传文件
  70. for (let i in this.files) {
  71. // this.upload(this.files[i]);
  72. if(this.videoConfigInfo.drive == 'oss') {
  73. this.handleAlyInUploading(this.files[i])
  74. }else if(this.videoConfigInfo.drive == 'qiniu'){
  75. this.handleQnyInUploading(this.files[i])
  76. }else {
  77. this.handleFileInUploading(this.files[i])
  78. }
  79. }
  80. },
  81. /* 保存上传视频 */
  82. saveVideoUrl(info, file) {
  83. const params = {};
  84. let formData = new FormData();
  85. params['r'] = 'mall/attachment/set-long-video-data';
  86. this.$request({
  87. params: params,
  88. method: 'post',
  89. data: {
  90. url: info.url,
  91. upload_type: 'bigVideos',
  92. old_name: info.name,
  93. attachment_group_id: this.uploadParams.attachment_group_id || 0,
  94. },
  95. }).then(e => {
  96. if (e.data.code === 1) {
  97. this.$message.error(e.data.msg);
  98. }
  99. file.response = e;
  100. file._complete = true;
  101. this.onSuccess(file);
  102. }).catch(e => {
  103. file._complete = true;
  104. });
  105. },
  106. /* 腾讯云上传 */
  107. handleFileInUploading(file) {
  108. const timestamp = new Date().getTime();
  109. const fileName = `${timestamp}_${file.rawFile.name}`
  110. const cos = new COS({
  111. SecretId: this.videoConfigInfo.secret_id,
  112. SecretKey: this.videoConfigInfo.secret_key,
  113. });
  114. cos.uploadFile({
  115. Bucket: this.videoConfigInfo.bucket, /* 填写自己的 bucket,必须字段 */
  116. Region: this.videoConfigInfo.area, /* 存储桶所在地域,必须字段 */
  117. Key: `videos/${fileName}`, /* 存储在桶里的对象键(例如:1.jpg,a/b/test.txt,图片.jpg)支持中文,必须字段 */
  118. Body: file.rawFile, // 上传文件对象
  119. SliceSize: 1024 * 1024 * 5, /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */
  120. onProgress: function(progressData) {
  121. console.log(JSON.stringify(progressData));
  122. }
  123. }, (err, data)=> {
  124. if (err) {
  125. console.log('上传失败', err);
  126. file._complete = true;
  127. this.onSuccess(file);
  128. } else {
  129. console.log('上传成功', data);
  130. let info = {
  131. url: `https://${data.Location}`,
  132. name: file.rawFile.name,
  133. }
  134. this.saveVideoUrl(info, file)
  135. }
  136. });
  137. },
  138. /* 七牛云上传 */
  139. async handleQnyInUploading(file) {
  140. const timestamp = new Date().getTime();
  141. const fileName = `${timestamp}_${file.rawFile.name}`
  142. let that = this
  143. let token = this.videoConfigInfo.token
  144. let config = {
  145. useCdnDomain: true,
  146. region: qiniu.region.z2
  147. };
  148. let putExtra = {
  149. fname: fileName,
  150. params: {},
  151. mimeType: null
  152. };
  153. let observable = qiniu.upload(file.rawFile, `videos/${fileName}`, token, putExtra, config);
  154. observable.subscribe({
  155. next(res) {
  156. console.log(res)
  157. },
  158. error(err) {
  159. console.log('上传失败', err)
  160. that.$message.error('上传失败');
  161. file._complete = true;
  162. that.onSuccess(file);
  163. },
  164. complete(res) {
  165. console.log('上传成功', res)
  166. let info = {
  167. url: `${that.videoConfigInfo.domain}/${res.key}`,
  168. name: file.rawFile.name,
  169. }
  170. that.saveVideoUrl(info, file)
  171. //上传成功之后把路径返回给后端
  172. },
  173. })
  174. },
  175. /* 阿里云上传 */
  176. async handleAlyInUploading(file) {
  177. const timestamp = new Date().getTime();
  178. const fileName = `${timestamp}_${file.rawFile.name}`
  179. const client = new OSS({
  180. // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  181. region: this.videoConfigInfo.region,
  182. endpoint: this.videoConfigInfo.endpoint,
  183. authorizationV4: true,
  184. // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
  185. accessKeyId: this.videoConfigInfo.secret_id,
  186. accessKeySecret: this.videoConfigInfo.secret_key,
  187. // 从STS服务获取的安全令牌(SecurityToken)。
  188. stsToken: this.videoConfigInfo.security_token,
  189. // 填写Bucket名称,例如examplebucket。
  190. bucket: this.videoConfigInfo.bucket,
  191. });
  192. const headers = {
  193. // 指定该Object被下载时的网页缓存行为。
  194. "Cache-Control": "no-cache",
  195. // 指定该Object被下载时的名称。
  196. "Content-Disposition": "example.txt",
  197. // 指定该Object被下载时的内容编码格式。
  198. "Content-Encoding": "utf-8",
  199. // 指定过期时间,单位为毫秒。
  200. Expires: "1000",
  201. // 指定Object的存储类型。
  202. "x-oss-storage-class": "Standard",
  203. // 指定Object标签,可同时设置多个标签。
  204. "x-oss-tagging": "Tag1=1&Tag2=2",
  205. // 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
  206. "x-oss-forbid-overwrite": "true",
  207. };
  208. // 指定上传到examplebucket的Object名称,例如exampleobject.txt。
  209. const options = {
  210. // 获取分片上传进度、断点和返回值。
  211. progress: (p, cpt, res) => {
  212. console.log(p);
  213. },
  214. // 设置并发上传的分片数量。
  215. parallel: 4,
  216. // 设置分片大小。默认值为1 MB,最小值为100 KB。
  217. partSize: 1024 * 1024,
  218. // headers,
  219. // 自定义元数据,通过HeadObject接口可以获取Object的元数据。
  220. meta: { year: 2020, people: "test" },
  221. mime: "text/plain",
  222. };
  223. //简单上传
  224. //const result = await client.put(name, file.rawFile, options);
  225. //console.log(result);
  226. // 分片上传。
  227. try {
  228. const res = await client.multipartUpload(`videos/${fileName}`, file.rawFile, {
  229. ...options,
  230. });
  231. console.log(res)
  232. let info = {
  233. url: `https://${this.videoConfigInfo.domain}/videos/${fileName}`,
  234. name: file.rawFile.name,
  235. }
  236. this.saveVideoUrl(info, file)
  237. } catch (err) {
  238. console.log(err);
  239. file._complete = true;
  240. that.onSuccess(file);
  241. }
  242. },
  243. onSuccess(file) {
  244. // 向父组件传递方法
  245. this.$emit('success', file);
  246. },
  247. },
  248. });
  249. </script>