上传插件,不包含上传的前端实现,只提供后端接口等,其他地方接入插件上传。包括上传进度、断点续传等

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import { Constants } from './utils/contants'
  2. import getFilemd5sum from './utils/utils'
  3. function FileFactory(file) {
  4. this.offset = 0; //用于断点续传,默认为 0
  5. this.BYTES_PER_CHUNK = 1024 * 1024
  6. this.file = file
  7. this.fileSize = file.size
  8. this.fileType = (file.name.split('.')[1]).toLowerCase()
  9. this.chunkNum = this.BYTES_PER_CHUNK > this.fileSize ? Math.ceil(this.fileSize / this.BYTES_PER_CHUNK) : 1
  10. this.chunkSize = this.BYTES_PER_CHUNK > this.fileSize ? this.fileSize : this.BYTES_PER_CHUNK
  11. }
  12. FileFactory.prototype.setOffset = function (offset) {
  13. this.offset = offset
  14. }
  15. export default function UploadSdk(host, origin, token, file) {
  16. this.handlers = [] //用于处理出触发事件
  17. this.host = host.indexOf('http:') > -1 ? 'http:'+ host: host
  18. this.origin = origin
  19. this.token = token
  20. this.file = file
  21. this.generateMd5 = function (callback) {
  22. getFilemd5sum(this.file).then(result => {
  23. callback(result)
  24. })
  25. }
  26. this.imageUploadAction = function () {
  27. return new Promise((resolve, reject) => {
  28. let fileFactory = new FileFactory(this.file)
  29. if (!fileFactory.fileType.match('[(jpg)|(png)|(gif)]+$')) {
  30. reject(Constants.IMAGE_TYPE_ERROR)
  31. }
  32. this.generateMd5((md5) => {
  33. this.md5 = md5
  34. this.postImage(this.md5, fileFactory).then(res => {
  35. resolve(res)
  36. }).catch((err) => {
  37. reject(err)
  38. })
  39. })
  40. })
  41. }
  42. this.videoUploadAction = function () {
  43. return new Promise((resolve, reject) => {
  44. if (!this.file.type.match('[(mp4)|(rmvb)|(flv)|(mpeg)|(avi)]+$')) {
  45. reject(Constants.VIDOE_TYPE_ERROR)
  46. }
  47. this.postVideo().then(res => {
  48. resolve(res)
  49. }).catch((err) => {
  50. reject(err)
  51. })
  52. })
  53. }
  54. this.postVideo = function () {
  55. const self = this
  56. return new Promise((resolve, reject) => {
  57. let xhr = new XMLHttpRequest()
  58. xhr.open('POST', this.host + Constants.VIDEO_MULTIPART + this.origin, true)
  59. xhr.withCredentials = true;
  60. xhr.setRequestHeader('Authorization', `Bearer ${this.token}`)
  61. xhr.setRequestHeader('Content-type', 'application/json')
  62. xhr.upload.addEventListener("progress", function updateProgress(oEvent) {
  63. if (oEvent.lengthComputable) {
  64. let percentComplete = oEvent.loaded / oEvent.total * 100;
  65. self.emitUpdateProgress(percentComplete)
  66. }
  67. }, false)
  68. let fd = new FormData()
  69. fd.append('file', this.file)
  70. fd.append('code_rate', 'ld,sd,hd')
  71. xhr.send(fd)
  72. xhr.onreadystatechange = function () {
  73. if (xhr.readyState === 4) {
  74. let obj = JSON.parse(xhr.responseText)
  75. if (xhr.status === 304 || (xhr.status >= 200 && xhr.status < 300)) {
  76. resolve({
  77. code: Constants.UPLOAD_SUCCESS_CODE,
  78. url: obj.url,
  79. msg: 'success'
  80. })
  81. } else {
  82. reject({
  83. code: Constants.UPLOAD_FAILED_CODE,
  84. url: '',
  85. msg: obj.message
  86. })
  87. }
  88. }
  89. }
  90. })
  91. }
  92. this.postImage = function (md5, fileFactory) {
  93. const self = this
  94. return new Promise((resolve, reject) => {
  95. let xhr = new XMLHttpRequest()
  96. xhr.upload.addEventListener("progress", function updateProgress(oEvent) {
  97. if (oEvent.lengthComputable) {
  98. let percentComplete = oEvent.loaded / oEvent.total * 100;
  99. self.emitUpdateProgress(percentComplete)
  100. }
  101. }, false)
  102. xhr.open('POSt', this.host + Constants.IMAGE_MULTIPART + this.origin, true)
  103. xhr.withCredentials = true
  104. xhr.setRequestHeader('Authorization', `Bearer ${this.token}`)
  105. xhr.setRequestHeader('X-Upload-File-Size', fileFactory.fileSize)
  106. xhr.setRequestHeader('X-Upload-Chunk-Index', 1 + '')
  107. xhr.setRequestHeader('X-Upload-Chunk-Num', fileFactory.chunkNum)
  108. xhr.setRequestHeader('X-Upload-Chunk-Size', fileFactory.chunkSize)
  109. xhr.setRequestHeader('X-Upload-Offset', fileFactory.offset + '')
  110. xhr.setRequestHeader('X-Upload-File-Md5', md5)
  111. xhr.setRequestHeader('X-Upload-File-Type', fileFactory.fileType)
  112. let fd = new FormData()
  113. fd.append('file', this.file)
  114. xhr.send(fd)
  115. xhr.onreadystatechange = function () {
  116. if (xhr.readyState === 4) {
  117. let obj = JSON.parse(xhr.responseText)
  118. if (xhr.status === 304 || (xhr.status >= 200 && xhr.status < 300)) {
  119. if (obj.status === 1) {
  120. resolve({
  121. code: Constants.UPLOAD_SUCCESS_CODE,
  122. url: obj.url,
  123. msg: 'success'
  124. })
  125. } else if (obj.status === 0) {
  126. fileFactory.setOffset(obj.msg)
  127. this.getAllResponseHeaders.postImage(md5, fileFactory)
  128. }
  129. } else {
  130. reject({
  131. code: Constants.UPLOAD_FAILED_CODE,
  132. url: '',
  133. msg: obj.message
  134. })
  135. }
  136. }
  137. }
  138. })
  139. }
  140. }
  141. UploadSdk.prototype = {
  142. onUpdateProgress: function(subscriber){
  143. let isExist = this.handlers.some(function(item){
  144. return item == subscriber;
  145. })
  146. if(!isExist){
  147. this.handlers.push(subscriber);
  148. }
  149. return this;
  150. },
  151. emitUpdateProgress: function(data){
  152. this.handlers.forEach(function(fn){
  153. fn(data)
  154. })
  155. return this;
  156. }
  157. }