@@ -1797,7 +1797,8 @@ | |||
"assert-plus": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", | |||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" | |||
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", | |||
"optional": true | |||
}, | |||
"assign-symbols": { | |||
"version": "1.0.0", | |||
@@ -2854,6 +2855,7 @@ | |||
"version": "1.0.8", | |||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", | |||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", | |||
"optional": true, | |||
"requires": { | |||
"delayed-stream": "~1.0.0" | |||
} | |||
@@ -3590,7 +3592,8 @@ | |||
"delayed-stream": { | |||
"version": "1.0.0", | |||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | |||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" | |||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", | |||
"optional": true | |||
}, | |||
"delegate": { | |||
"version": "3.2.0", | |||
@@ -3744,9 +3747,9 @@ | |||
} | |||
}, | |||
"dropzone": { | |||
"version": "5.7.0", | |||
"resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.0.tgz", | |||
"integrity": "sha512-kOltiZXH5cO/72I22JjE+w6BoT6uaVLfWdFMsi1PMKFkU6BZWpqRwjnsRm0o6ANGTBuZar5Piu7m/CbKqRPiYg==" | |||
"version": "5.7.2", | |||
"resolved": "https://registry.npm.taobao.org/dropzone/download/dropzone-5.7.2.tgz?cache=0&sync_timestamp=1596009792692&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdropzone%2Fdownload%2Fdropzone-5.7.2.tgz", | |||
"integrity": "sha1-kb7hVy3aUV1AkB2jBLx53d8wm0w=" | |||
}, | |||
"duplexer2": { | |||
"version": "0.0.2", | |||
@@ -4806,7 +4809,8 @@ | |||
"extsprintf": { | |||
"version": "1.3.0", | |||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", | |||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" | |||
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", | |||
"optional": true | |||
}, | |||
"fancy-log": { | |||
"version": "1.3.3", | |||
@@ -7621,7 +7625,8 @@ | |||
"jsbn": { | |||
"version": "0.1.1", | |||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", | |||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" | |||
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", | |||
"optional": true | |||
}, | |||
"jsesc": { | |||
"version": "2.5.2", | |||
@@ -8677,12 +8682,14 @@ | |||
"mime-db": { | |||
"version": "1.44.0", | |||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", | |||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" | |||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", | |||
"optional": true | |||
}, | |||
"mime-types": { | |||
"version": "2.1.27", | |||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", | |||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", | |||
"optional": true, | |||
"requires": { | |||
"mime-db": "1.44.0" | |||
} | |||
@@ -13654,7 +13661,8 @@ | |||
"tweetnacl": { | |||
"version": "0.14.5", | |||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", | |||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" | |||
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", | |||
"optional": true | |||
}, | |||
"type": { | |||
"version": "1.2.0", | |||
@@ -18,7 +18,7 @@ | |||
"css-loader": "3.5.3", | |||
"cssnano": "4.1.10", | |||
"domino": "2.1.5", | |||
"dropzone": "5.7.0", | |||
"dropzone": "5.7.2", | |||
"fast-glob": "3.2.2", | |||
"file-loader": "6.0.0", | |||
"fomantic-ui": "2.8.4", | |||
@@ -1,362 +0,0 @@ | |||
<template> | |||
<uploader | |||
ref="uploader" | |||
:options="options" | |||
:autoStart="false" | |||
@file-added="onFileAdded" | |||
fileStatusText="fileStatusText" | |||
class="uploader-app"> | |||
<uploader-unsupport></uploader-unsupport> | |||
<uploader-drop> | |||
<p>拖动文件</p> | |||
<uploader-btn>选择文件</uploader-btn> | |||
</uploader-drop> | |||
<uploader-list></uploader-list> | |||
<p>文件处理状态:{{status}}</p> | |||
<p>文件上传进度:{{progress}}%</p> | |||
</uploader> | |||
</template> | |||
<script> | |||
import SparkMD5 from 'spark-md5'; | |||
import axios from 'axios' | |||
import qs from 'qs' | |||
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||
export default { | |||
data () { | |||
return { | |||
attrs: { | |||
accept: '*' | |||
}, | |||
fileStatusText: { | |||
success: '上传成功', | |||
error: '上传出错了', | |||
uploading: '上传中...', | |||
paused: '暂停', | |||
waiting: '等待中...', | |||
cmd5: '计算md5...' | |||
}, | |||
fileStatusText: (status, response) => { | |||
return this.fileStatusText[status]; | |||
}, | |||
progress: 0, | |||
status: '初始状态', | |||
} | |||
}, | |||
created() { | |||
//const uploaderInstance = this.$refs.uploader; | |||
}, | |||
mounted () { | |||
this.$nextTick(() => { | |||
window.uploader = this.$refs.uploader.uploader | |||
}) | |||
}, | |||
methods: { | |||
onFileAdded(file) { | |||
file.datasetId = document.getElementById("datasetId").getAttribute("datasetId"); | |||
this.progress=0; | |||
this.status='初始状态'; | |||
// 计算MD5 | |||
this.computeMD5(file); | |||
}, | |||
getSuccessChunks(file) { | |||
return new Promise((resolve, reject) => { | |||
axios.get('/attachments/get_chunks', {params :{ | |||
md5: file.uniqueIdentifier, | |||
_csrf: csrf | |||
}}).then(function (response) { | |||
file.uploadID = response.data.uploadID; | |||
file.uuid = response.data.uuid; | |||
file.uploaded = response.data.uploaded; | |||
file.chunks = response.data.chunks; | |||
file.attachID = response.data.attachID; | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
}, | |||
newMultiUpload(file) { | |||
return new Promise((resolve, reject) => { | |||
axios.get('/attachments/new_multipart', {params :{ | |||
totalChunkCounts: file.totalChunkCounts, | |||
md5: file.uniqueIdentifier, | |||
size: file.size, | |||
fileType: file.fileType, | |||
_csrf: csrf | |||
}}).then(function (response) { | |||
file.uploadID = response.data.uploadID; | |||
file.uuid = response.data.uuid; | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
}, | |||
multipartUpload(file) { | |||
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, | |||
chunkSize = 1024*1024*64, | |||
chunks = Math.ceil(file.size / chunkSize), | |||
currentChunk = 0, | |||
fileReader = new FileReader(), | |||
time = new Date().getTime(); | |||
function loadNext() { | |||
let start = currentChunk * chunkSize; | |||
let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; | |||
fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); | |||
} | |||
function checkSuccessChunks() { | |||
var index = successChunks.indexOf((currentChunk+1).toString()) | |||
if (index == -1) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
function getUploadChunkUrl(currentChunk, partSize) { | |||
return new Promise((resolve, reject) => { | |||
axios.get('/attachments/get_multipart_url', {params :{ | |||
uuid: file.uuid, | |||
uploadID: file.uploadID, | |||
size: partSize, | |||
chunkNumber: currentChunk+1, | |||
_csrf: csrf | |||
}}).then(function (response) { | |||
urls[currentChunk] = response.data.url | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
} | |||
function uploadMinio(url, e) { | |||
return new Promise((resolve, reject) => { | |||
axios.put(url, e.target.result | |||
).then(function (res) { | |||
etags[currentChunk] = res.headers.etag; | |||
resolve(res); | |||
}).catch(function (err) { | |||
console.log(err); | |||
reject(err); | |||
}); | |||
}); | |||
} | |||
function updateChunk(currentChunk) { | |||
return new Promise((resolve, reject) => { | |||
axios.post('/attachments/update_chunk', qs.stringify({ | |||
uuid: file.uuid, | |||
chunkNumber: currentChunk+1, | |||
etag: etags[currentChunk], | |||
_csrf: csrf | |||
})).then(function (response) { | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
} | |||
async function uploadChunk(e) { | |||
if (!checkSuccessChunks()) { | |||
let start = currentChunk * chunkSize; | |||
let partSize = ((start + chunkSize) >= file.size) ? file.size -start : chunkSize; | |||
//获取分片上传url | |||
await getUploadChunkUrl(currentChunk, partSize); | |||
if (urls[currentChunk] != "") { | |||
//上传到minio | |||
await uploadMinio(urls[currentChunk], e); | |||
if (etags[currentChunk] != "") { | |||
//更新数据库:分片上传结果 | |||
await updateChunk(currentChunk); | |||
} else { | |||
return; | |||
} | |||
} else { | |||
return; | |||
} | |||
} | |||
}; | |||
function completeUpload(){ | |||
return new Promise((resolve, reject) => { | |||
axios.post('/attachments/complete_multipart', qs.stringify({ | |||
uuid: file.uuid, | |||
uploadID: file.uploadID, | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
_csrf: csrf | |||
})).then(function (response) { | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
} | |||
var successChunks = new Array(); | |||
var successParts = new Array(); | |||
successParts = file.chunks.split(","); | |||
for (let i = 0; i < successParts.length; i++) { | |||
successChunks[i] = successParts[i].split("-")[0].split("\"")[1]; | |||
} | |||
var urls = new Array(); | |||
var etags = new Array(); | |||
console.log('上传分片...'); | |||
this.status='上传中'; | |||
{ | |||
loadNext(); | |||
fileReader.onload = async (e) => { | |||
await uploadChunk(e); | |||
currentChunk++; | |||
if (currentChunk < chunks) { | |||
console.log(`第${currentChunk}个分片上传完成, 开始第${currentChunk +1}/${chunks}个分片上传`); | |||
this.progress = Math.ceil((currentChunk / chunks)*100); | |||
await loadNext(); | |||
} else { | |||
await completeUpload(); | |||
console.log(`文件上传完成:${file.name} \n分片:${chunks} 大小:${file.size} 用时:${(new Date().getTime() - time)/1000} s`); | |||
this.progress = 100; | |||
this.status='上传完成'; | |||
window.location.reload(); | |||
} | |||
}; | |||
} | |||
}, | |||
//计算MD5 | |||
computeMD5(file) { | |||
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, | |||
chunkSize = 1024*1024*64, | |||
chunks = Math.ceil(file.size / chunkSize), | |||
currentChunk = 0, | |||
spark = new SparkMD5.ArrayBuffer(), | |||
fileReader = new FileReader(); | |||
let time = new Date().getTime(); | |||
console.log('计算MD5...') | |||
this.status='计算MD5'; | |||
file.totalChunkCounts = chunks; | |||
loadNext(); | |||
fileReader.onload = (e) => { | |||
spark.append(e.target.result); // Append array buffer | |||
currentChunk++; | |||
if (currentChunk < chunks) { | |||
console.log(`第${currentChunk}分片解析完成, 开始第${currentChunk +1}/${chunks}分片解析`); | |||
loadNext(); | |||
} else { | |||
let md5 = spark.end(); | |||
console.log(`MD5计算完成:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${(new Date().getTime() - time)/1000} s`); | |||
spark.destroy(); //释放缓存 | |||
file.uniqueIdentifier = md5; //将文件md5赋值给文件唯一标识 | |||
file.cmd5 = false; //取消计算md5状态 | |||
this.computeMD5Success(file); | |||
} | |||
}; | |||
fileReader.onerror = () => { | |||
console.warn('oops, something went wrong.'); | |||
file.cancel(); | |||
}; | |||
function loadNext() { | |||
let start = currentChunk * chunkSize; | |||
let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; | |||
fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end)); | |||
} | |||
}, | |||
async computeMD5Success(file) { | |||
await this.getSuccessChunks(file); | |||
if (file.uploadID == "" || file.uuid == "") { //未上传过 | |||
await this.newMultiUpload(file); | |||
if (file.uploadID != "" && file.uuid != "") { | |||
file.chunks = ""; | |||
this.multipartUpload(file); | |||
} else { | |||
//失败如何处理 | |||
return; | |||
} | |||
} else { | |||
if (file.uploaded == "1") { //已上传成功 | |||
//秒传 | |||
if (file.attachID == "0") { //删除数据集记录,未删除文件 | |||
await addAttachment(file); | |||
} | |||
console.log("文件已上传完成"); | |||
this.progress = 100; | |||
this.status='上传完成'; | |||
window.location.reload(); | |||
} else { | |||
//断点续传 | |||
this.multipartUpload(file); | |||
} | |||
} | |||
function addAttachment(file){ | |||
return new Promise((resolve, reject) => { | |||
axios.post('/attachments/add', qs.stringify({ | |||
uuid: file.uuid, | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
_csrf: csrf | |||
})).then(function (response) { | |||
resolve(response); | |||
}).catch(function (error) { | |||
console.log(error); | |||
reject(error); | |||
}); | |||
}) | |||
} | |||
} | |||
} | |||
} | |||
</script> | |||
<style> | |||
.uploader-app { | |||
width: 850px; | |||
padding: 15px; | |||
margin: 40px auto 0; | |||
font-size: 12px; | |||
box-shadow: 0 0 10px rgba(0, 0, 0, .4); | |||
} | |||
.uploader-app .uploader-btn { | |||
margin-right: 40px; | |||
} | |||
.uploader-app .uploader-list { | |||
max-height: 440px; | |||
overflow: auto; | |||
overflow-x: hidden; | |||
overflow-y: auto; | |||
} | |||
</style> |
@@ -0,0 +1,331 @@ | |||
<template> | |||
<div class="dropzone-wrapper"> | |||
<div id="dropzone" class="dropzone"> | |||
</div> | |||
<p>文件处理状态:{{ status }}</p> | |||
<p>文件上传进度:{{ progress }}%</p> | |||
</div> | |||
</template> | |||
<script> | |||
import Dropzone from 'dropzone/dist/dropzone.js'; | |||
// import 'dropzone/dist/dropzone.css' | |||
import createDropzone from '../features/dropzone.js'; | |||
import SparkMD5 from 'spark-md5'; | |||
import axios from 'axios'; | |||
import qs from 'qs'; | |||
const { | |||
AppSubUrl, | |||
StaticUrlPrefix, | |||
csrf | |||
} = window.config; | |||
export default { | |||
data() { | |||
return { | |||
dropzoneUploader: null, | |||
maxFiles: 1, | |||
maxFilesize: 1 * 1024 * 1024 * 1024 * 1024, | |||
acceptedFiles: '*/*', | |||
progress: 0, | |||
status: '等待上传', | |||
} | |||
}, | |||
async mounted() { | |||
const dropzoneUploader = await createDropzone("div#dropzone", { | |||
url: '/todouploader', | |||
maxFiles: this.maxFiles, | |||
maxFilesize: this.maxFileSize, | |||
timeout: 0, | |||
autoQueue: false, | |||
}) | |||
dropzoneUploader.on("addedfile", (file) => { | |||
setTimeout(() => { | |||
file.accepted && this.onFileAdded(file); | |||
}, 200); | |||
}); | |||
dropzoneUploader.on("maxfilesexceeded", function(file) { | |||
if (this.files[0].status !== 'success') { | |||
alert('请等待第一个文件传输完成') | |||
this.removeFile(file) | |||
return | |||
} | |||
this.removeAllFiles(); | |||
this.addFile(file); | |||
}); | |||
this.dropzoneUploader = dropzoneUploader | |||
}, | |||
methods: { | |||
resetStatus() { | |||
this.progress = 0 | |||
this.status = '' | |||
}, | |||
updateProgress(file, progress) { | |||
file.previewTemplate.querySelector(".dz-upload").style.width = `${progress}%`; | |||
}, | |||
emitDropzoneSuccess(file) { | |||
file.status = Dropzone.SUCCESS; | |||
this.dropzoneUploader.emit("success", file); | |||
this.dropzoneUploader.emit("complete", file); | |||
}, | |||
onFileAdded(file) { | |||
file.datasetId = document.getElementById("datasetId").getAttribute("datasetId"); | |||
this.resetStatus() | |||
this.computeMD5(file); | |||
}, | |||
finishUpload(file) { | |||
this.emitDropzoneSuccess(file) | |||
setTimeout(() => { | |||
window.location.reload(); | |||
}, 1000); | |||
}, | |||
computeMD5(file) { | |||
this.resetStatus() | |||
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, | |||
chunkSize = 1024 * 1024 * 64, | |||
chunks = Math.ceil(file.size / chunkSize), | |||
currentChunk = 0, | |||
spark = new SparkMD5.ArrayBuffer(), | |||
fileReader = new FileReader(); | |||
let time = new Date().getTime(); | |||
// console.log('计算MD5...') | |||
this.status = '计算MD5'; | |||
file.totalChunkCounts = chunks; | |||
loadNext(); | |||
fileReader.onload = (e) => { | |||
fileLoaded.call(this, e) | |||
}; | |||
fileReader.onerror = (err) => { | |||
console.warn('oops, something went wrong.', err); | |||
file.cancel(); | |||
}; | |||
function fileLoaded(e){ | |||
spark.append(e.target.result); // Append array buffer | |||
currentChunk++; | |||
if (currentChunk < chunks) { | |||
// console.log(`第${currentChunk}分片解析完成, 开始第${currentChunk +1}/${chunks}分片解析`); | |||
this.status = `加载文件 ${(currentChunk/chunks*100).toFixed(2)}% (${currentChunk}/${chunks})`; | |||
this.updateProgress(file, (currentChunk/chunks*100).toFixed(2)) | |||
loadNext(); | |||
return | |||
} | |||
let md5 = spark.end(); | |||
console.log( | |||
`MD5计算完成:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${(new Date().getTime() - time)/1000} s` | |||
); | |||
spark.destroy(); //释放缓存 | |||
file.uniqueIdentifier = md5; //将文件md5赋值给文件唯一标识 | |||
file.cmd5 = false; //取消计算md5状态 | |||
this.computeMD5Success(file); | |||
} | |||
function loadNext() { | |||
let start = currentChunk * chunkSize; | |||
let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; | |||
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); | |||
} | |||
}, | |||
async computeMD5Success(md5edFile) { | |||
const file = await this.getSuccessChunks(md5edFile); | |||
if (file.uploadID == "" || file.uuid == "") { //未上传过 | |||
await this.newMultiUpload(file); | |||
if (file.uploadID != "" && file.uuid != "") { | |||
file.chunks = ""; | |||
this.multipartUpload(file); | |||
} else { | |||
//失败如何处理 | |||
return; | |||
} | |||
return | |||
} | |||
if (file.uploaded == "1") { //已上传成功 | |||
//秒传 | |||
if (file.attachID == "0") { //删除数据集记录,未删除文件 | |||
await addAttachment(file); | |||
} | |||
console.log("文件已上传完成"); | |||
this.progress = 100; | |||
this.status = '上传完成'; | |||
this.finishUpload(file) | |||
} else { | |||
//断点续传 | |||
this.multipartUpload(file); | |||
} | |||
async function addAttachment(file) { | |||
return await axios.post('/attachments/add', qs.stringify({ | |||
uuid: file.uuid, | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
_csrf: csrf | |||
})) | |||
} | |||
}, | |||
async getSuccessChunks(file) { | |||
const params = { | |||
params: { | |||
md5: file.uniqueIdentifier, | |||
_csrf: csrf | |||
} | |||
} | |||
try { | |||
const response = await axios.get('/attachments/get_chunks', params) | |||
file.uploadID = response.data.uploadID; | |||
file.uuid = response.data.uuid; | |||
file.uploaded = response.data.uploaded; | |||
file.chunks = response.data.chunks; | |||
file.attachID = response.data.attachID; | |||
return file | |||
} catch(error) { | |||
console.log("getSuccessChunks catch: ", error); | |||
return null | |||
} | |||
}, | |||
async newMultiUpload(file) { | |||
const res = await axios.get('/attachments/new_multipart', { | |||
params: { | |||
totalChunkCounts: file.totalChunkCounts, | |||
md5: file.uniqueIdentifier, | |||
size: file.size, | |||
fileType: file.fileType, | |||
_csrf: csrf | |||
} | |||
}) | |||
file.uploadID = res.data.uploadID; | |||
file.uuid = res.data.uuid; | |||
}, | |||
multipartUpload(file) { | |||
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice, | |||
chunkSize = 1024 * 1024 * 64, | |||
chunks = Math.ceil(file.size / chunkSize), | |||
currentChunk = 0, | |||
fileReader = new FileReader(), | |||
time = new Date().getTime(); | |||
function loadNext() { | |||
let start = currentChunk * chunkSize; | |||
let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize; | |||
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end)); | |||
} | |||
function checkSuccessChunks() { | |||
var index = successChunks.indexOf((currentChunk + 1).toString()) | |||
if (index == -1) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
async function getUploadChunkUrl(currentChunk, partSize) { | |||
const res = await axios.get('/attachments/get_multipart_url', { | |||
params: { | |||
uuid: file.uuid, | |||
uploadID: file.uploadID, | |||
size: partSize, | |||
chunkNumber: currentChunk + 1, | |||
_csrf: csrf | |||
} | |||
}) | |||
console.log("getUploadChunkUrl: ", res) | |||
urls[currentChunk] = res.data.url | |||
} | |||
async function uploadMinio(url, e) { | |||
const res = await axios.put(url, e.target.result) | |||
etags[currentChunk] = res.headers.etag; | |||
} | |||
async function updateChunk(currentChunk) { | |||
await axios.post('/attachments/update_chunk', qs.stringify({ | |||
uuid: file.uuid, | |||
chunkNumber: currentChunk + 1, | |||
etag: etags[currentChunk], | |||
_csrf: csrf | |||
})) | |||
} | |||
async function uploadChunk(e) { | |||
if (!checkSuccessChunks()) { | |||
let start = currentChunk * chunkSize; | |||
let partSize = ((start + chunkSize) >= file.size) ? file.size - start : chunkSize; | |||
//获取分片上传url | |||
await getUploadChunkUrl(currentChunk, partSize); | |||
if (urls[currentChunk] != "") { | |||
//上传到minio | |||
await uploadMinio(urls[currentChunk], e); | |||
if (etags[currentChunk] != "") { | |||
//更新数据库:分片上传结果 | |||
await updateChunk(currentChunk); | |||
} else { | |||
return; | |||
} | |||
} else { | |||
return; | |||
} | |||
} | |||
}; | |||
async function completeUpload() { | |||
return await axios.post('/attachments/complete_multipart', qs.stringify({ | |||
uuid: file.uuid, | |||
uploadID: file.uploadID, | |||
file_name: file.name, | |||
size: file.size, | |||
dataset_id: file.datasetId, | |||
_csrf: csrf | |||
})) | |||
} | |||
var successChunks = new Array(); | |||
var successParts = new Array(); | |||
successParts = file.chunks.split(","); | |||
for (let i = 0; i < successParts.length; i++) { | |||
successChunks[i] = successParts[i].split("-")[0].split("\"")[1]; | |||
} | |||
var urls = new Array(); | |||
var etags = new Array(); | |||
console.log('上传分片...'); | |||
this.status = '上传中' | |||
loadNext(); | |||
fileReader.onload = async (e) => { | |||
await uploadChunk(e); | |||
currentChunk++; | |||
if (currentChunk < chunks) { | |||
console.log(`第${currentChunk}个分片上传完成, 开始第${currentChunk +1}/${chunks}个分片上传`); | |||
this.progress = Math.ceil((currentChunk / chunks) * 100); | |||
this.updateProgress(file, (currentChunk/chunks*100).toFixed(2)) | |||
await loadNext(); | |||
} else { | |||
await completeUpload(); | |||
console.log(`文件上传完成:${file.name} \n分片:${chunks} 大小:${file.size} 用时:${(new Date().getTime() - time)/1000} s`); | |||
this.progress = 100; | |||
this.status = '上传完成'; | |||
this.finishUpload(file) | |||
} | |||
}; | |||
}, | |||
} | |||
} | |||
</script> | |||
<style> | |||
.dropzone-wrapper { | |||
margin: 2em auto ; | |||
} | |||
</style> |
@@ -8,6 +8,7 @@ import './polyfills.js'; | |||
import Vue from 'vue'; | |||
import 'jquery.are-you-sure'; | |||
import './vendor/semanticdropdown.js'; | |||
import VueSimpleUploader from 'vue-simple-uploader'; | |||
import {svg} from './utils.js'; | |||
import initContextPopups from './features/contextpopup.js'; | |||
@@ -21,11 +22,9 @@ import highlight from './features/highlight.js'; | |||
import ActivityTopAuthors from './components/ActivityTopAuthors.vue'; | |||
import {initNotificationsTable, initNotificationCount} from './features/notification.js'; | |||
import {createCodeEditor} from './features/codeeditor.js'; | |||
import App from './App.vue' | |||
import uploader from 'vue-simple-uploader' | |||
Vue.use(uploader); | |||
import MinioUploader from './components/MinioUploader.vue'; | |||
Vue.use(VueSimpleUploader); | |||
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||
@@ -3175,8 +3174,8 @@ function initVueUploader() { | |||
/* eslint-disable no-new */ | |||
new Vue({ | |||
el: '#uploader', | |||
components: { App }, | |||
template: '<App/>' | |||
components: {MinioUploader}, | |||
template: '<MinioUploader />' | |||
}); | |||
} | |||