Compare commits
No commits in common. "0487b5200181de87b2c7dc43aa019fc756390410" and "4b8e15abae576de0d8136c6a18a593ce36414af6" have entirely different histories.
0487b52001
...
4b8e15abae
|
@ -98,42 +98,30 @@ public class SysOssController extends BaseController {
|
||||||
*/
|
*/
|
||||||
@Log(title = "本地文件上传", businessType = BusinessType.INSERT)
|
@Log(title = "本地文件上传", businessType = BusinessType.INSERT)
|
||||||
@PostMapping("/addPartsUpload")
|
@PostMapping("/addPartsUpload")
|
||||||
public R<Map<String, String>> addPartsUpload(@RequestPart("file") MultipartFile file) {
|
public R<Map<String, String>> addPartsUpload(@RequestPart("file") MultipartFile file, HttpServletRequest req) {
|
||||||
Map<String,String> map=new HashMap<>();
|
Map<String,String> map=new HashMap<>();
|
||||||
|
String realPath = req.getSession().getServletContext().getRealPath("/uploadFile/");
|
||||||
String filePath = uploadPath + "/file/upload/";
|
String format = sdf.format(new Date());
|
||||||
|
///www/wwwroot/guanwang/web/image/file/upload/
|
||||||
|
// String filePath=uploadPath+"/file/upload/";
|
||||||
|
File folder = new File(realPath + format);
|
||||||
|
if (!folder.isDirectory()){
|
||||||
|
folder.mkdirs();
|
||||||
|
}
|
||||||
|
String oldName = file.getOriginalFilename();
|
||||||
|
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."), oldName.length());
|
||||||
try {
|
try {
|
||||||
if (file.isEmpty()) {
|
file.transferTo(new File(realPath,newName));
|
||||||
return R.warn("文件为空");
|
String filePath = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/uploadFile" + format + newName;
|
||||||
}
|
Long image = iSysImageService.uploadImage(newName,filePath);
|
||||||
|
map.put("url",filePath);
|
||||||
String fileName = System.currentTimeMillis() + "-" + file.getOriginalFilename();
|
map.put("fileName",newName);
|
||||||
//文件上传的路径(当前项目的根目录)
|
|
||||||
|
|
||||||
System.err.println(filePath);
|
|
||||||
// 创建目标目录(如果不存在)
|
|
||||||
File directory = new File(filePath);
|
|
||||||
if (!directory.exists()) {
|
|
||||||
directory.mkdirs();
|
|
||||||
}
|
|
||||||
// 保存文件到目标目录
|
|
||||||
File uploadFile = new File(directory.getAbsolutePath() + File.separator + fileName);
|
|
||||||
file.transferTo(uploadFile);
|
|
||||||
//上传服务器地址
|
|
||||||
String pathFan = filePath.replace("\\", "/");
|
|
||||||
//filePath获取到的地址斜杠是“ \ ”的(单斜杠是特殊符号,得用双斜杠代替),得换成“ / ”才能访问到
|
|
||||||
//返回全路径图片地址
|
|
||||||
String returnPath = ("http://47.121.27.78:8008/upload/" + fileName).replace("\\", "/");
|
|
||||||
//修改数据库
|
|
||||||
Long image = iSysImageService.uploadImage(fileName, returnPath);
|
|
||||||
System.err.println("替换后:" + pathFan);
|
|
||||||
map.put("url", returnPath);
|
|
||||||
map.put("fileName", fileName);
|
|
||||||
map.put("ossId",image.toString());
|
map.put("ossId",image.toString());
|
||||||
return R.ok(map);
|
return R.ok(map);
|
||||||
} catch (IOException e) {
|
} catch (IOException ex) {
|
||||||
return R.warn("文件上传失败: " + e);
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return R.warn("文件上传失败!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,12 +49,6 @@ public class GwIndex extends BaseEntity {
|
||||||
*/
|
*/
|
||||||
private String titleEnglish;
|
private String titleEnglish;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 链接
|
|
||||||
*/
|
|
||||||
private String twLink;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务名称英文描述
|
* 业务名称英文描述
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -60,11 +60,13 @@ public class FileChunkFilelistBo extends BaseEntity {
|
||||||
/**
|
/**
|
||||||
* 创建者id
|
* 创建者id
|
||||||
*/
|
*/
|
||||||
|
@NotNull(message = "创建者id不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
private Long createUserId;
|
private Long createUserId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新者id
|
* 更新者id
|
||||||
*/
|
*/
|
||||||
|
@NotNull(message = "更新者id不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
private Long updateUserId;
|
private Long updateUserId;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,11 +40,6 @@ public class GwIndexBo extends BaseEntity {
|
||||||
*/
|
*/
|
||||||
private String fileType;
|
private String fileType;
|
||||||
|
|
||||||
/**
|
|
||||||
* 链接
|
|
||||||
*/
|
|
||||||
private String twLink;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 业务类型 0:石油化工业务 1:基建业务 2:铁矿石业务 3:燃气业务
|
* 业务类型 0:石油化工业务 1:基建业务 2:铁矿石业务 3:燃气业务
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -59,11 +59,6 @@ public class GwIndexVo {
|
||||||
@ExcelProperty(value = "业务名称")
|
@ExcelProperty(value = "业务名称")
|
||||||
private String businessName;
|
private String businessName;
|
||||||
|
|
||||||
/**
|
|
||||||
* 链接
|
|
||||||
*/
|
|
||||||
private String twLink;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 图片标题英文描述
|
* 图片标题英文描述
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -310,7 +310,7 @@ public class FileChunkFilelistServiceImpl implements IFileChunkFilelistService {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.error("合并出现错误:" + e);
|
log.error("合并出现错误:" + e.getMessage(), e);
|
||||||
throw new RuntimeException("合并出现错误," + e.getMessage());
|
throw new RuntimeException("合并出现错误," + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,327 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="global-uploader">
|
<div>
|
||||||
|
<el-upload>
|
||||||
<!-- 上传 -->
|
<i class="el-icon-plus"></i>
|
||||||
<uploader
|
</el-upload>
|
||||||
ref="uploader"
|
|
||||||
:options="options"
|
|
||||||
:autoStart="false"
|
|
||||||
@file-added="onFileAdded"
|
|
||||||
@file-success="onFileSuccess"
|
|
||||||
@file-progress="onFileProgress"
|
|
||||||
@file-error="onFileError"
|
|
||||||
class="uploader-app">
|
|
||||||
<uploader-unsupport></uploader-unsupport>
|
|
||||||
|
|
||||||
<uploader-btn id="global-uploader-btn" :attrs="attrs" ref="uploadBtn">选择文件</uploader-btn>
|
|
||||||
|
|
||||||
<uploader-list v-show="panelShow">
|
|
||||||
<div class="file-panel" slot-scope="props" :class="{'collapse': collapse}">
|
|
||||||
<div class="file-title">
|
|
||||||
<h2>文件列表</h2>
|
|
||||||
<div class="operate">
|
|
||||||
<el-button @click="fileListShow" type="text" :title="collapse ? '展开':'折叠' ">
|
|
||||||
<i class="el-icon-d-caret" style="color:black;font-size: 18px"
|
|
||||||
:class="collapse ? 'inuc-fullscreen': 'inuc-minus-round'"></i>
|
|
||||||
</el-button>
|
|
||||||
<el-button @click="close" type="text" title="关闭">
|
|
||||||
<i class="el-icon-close" style="color:black;font-size: 18px"></i>
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="file-list">
|
|
||||||
<li v-for="file in props.fileList" :key="file.id">
|
|
||||||
<uploader-file :class="'file_' + file.id" ref="files" :file="file" :list="true"></uploader-file>
|
|
||||||
</li>
|
|
||||||
<div class="no-file" v-if="!props.fileList.length"><i class="iconfont icon-empty-file"></i> 暂无待上传文件</div>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</uploader-list>
|
|
||||||
|
|
||||||
</uploader>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* 全局上传插件
|
|
||||||
* 调用方法:Bus.$emit('openUploader', {}) 打开文件选择框,参数为需要传递的额外参数
|
|
||||||
* 监听函数:Bus.$on('fileAdded', fn); 文件选择后的回调
|
|
||||||
* Bus.$on('fileSuccess', fn); 文件上传成功的回调
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { getToken } from '@/utils/auth'
|
|
||||||
import {ACCEPT_CONFIG} from '@/assets/js/config'
|
|
||||||
import Bus from '@/assets/js/bus'
|
|
||||||
import SparkMD5 from 'spark-md5';
|
|
||||||
import { fileMerge } from '@/api/system/file/fileuploader/fileuploader';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
options: {
|
|
||||||
// 目标上传 URL
|
|
||||||
target: process.env.VUE_APP_BASE_API +'/official/chunkFilelist/upload',
|
|
||||||
//分块大小
|
|
||||||
chunkSize: 5 * 1024 * 1000,
|
|
||||||
//上传文件时文件的参数名,默认file
|
|
||||||
fileParameterName: 'file',
|
|
||||||
//并发上传数
|
|
||||||
//simultaneousUploads: 1,
|
|
||||||
//最大自动失败重试上传次数
|
|
||||||
maxChunkRetries: 0,
|
|
||||||
//重试间隔 单位毫秒
|
|
||||||
//chunkRetryInterval: 5000,
|
|
||||||
//是否开启服务器分片校验
|
|
||||||
testChunks: true,
|
|
||||||
// 服务器分片校验函数,秒传及断点续传基础
|
|
||||||
checkChunkUploadedByResponse: function (chunk, message) {
|
|
||||||
let objMessage = JSON.parse(message);
|
|
||||||
if (objMessage.skipUpload) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0
|
|
||||||
},
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Bearer ' + getToken()
|
|
||||||
},
|
|
||||||
// 额外的自定义查询参数
|
|
||||||
query() {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
attrs: {
|
|
||||||
accept: ACCEPT_CONFIG.getAll()
|
|
||||||
},
|
|
||||||
panelShow: false, //选择文件后,展示上传panel
|
|
||||||
collapse: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
//接收子组件触发的事件
|
|
||||||
Bus.$on('openUploader', query => {
|
|
||||||
this.params = query || {};
|
|
||||||
this.options.headers.Authorization = 'Bearer ' + query.token
|
|
||||||
|
|
||||||
|
|
||||||
if (this.$refs.uploadBtn) {
|
|
||||||
$("#global-uploader-btn").click();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
//Uploader实例
|
|
||||||
uploader() {
|
|
||||||
return this.$refs.uploader.uploader;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
onFileAdded(file) {
|
|
||||||
this.panelShow = true;
|
|
||||||
this.computeMD5(file);
|
|
||||||
|
|
||||||
Bus.$emit('fileAdded');
|
|
||||||
},
|
|
||||||
//上传过程中,会不断触发file-progress上传进度的回调
|
|
||||||
onFileProgress(rootFile, file, chunk) {
|
|
||||||
console.log(`上传中 ${file.name},chunk:${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`)
|
|
||||||
},
|
|
||||||
onFileSuccess(rootFile, file, response, chunk) {
|
|
||||||
|
|
||||||
let res = JSON.parse(response);
|
|
||||||
|
|
||||||
// TODO 如有需要 解开注释 和后台协议如何处理这种情况:服务器自定义的错误(即虽返回200,但是是错误的情况),这种错误是Uploader无法拦截的
|
|
||||||
// if (!res.result) {
|
|
||||||
// this.$message({message: res.message, type: 'error'});
|
|
||||||
// // 文件状态设为“失败”
|
|
||||||
// this.statusSet(file.id, 'failed');
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 如果服务端返回需要合并
|
|
||||||
if (res.data.needMerge) {
|
|
||||||
// 文件状态设为“合并中”
|
|
||||||
this.statusSet(file.id, 'merging');
|
|
||||||
let param = {
|
|
||||||
'filename': rootFile.name,
|
|
||||||
'identifier': rootFile.uniqueIdentifier,
|
|
||||||
'totalSize': rootFile.size
|
|
||||||
}
|
|
||||||
this.customMerge(param, file.id);
|
|
||||||
|
|
||||||
// 不需要合并
|
|
||||||
} else {
|
|
||||||
Bus.$emit('fileSuccess');
|
|
||||||
console.log('上传成功');
|
|
||||||
this.panelShow = false
|
|
||||||
Bus.$emit('refreshFileList'); // 触发刷新文件列表事件
|
|
||||||
}
|
|
||||||
},
|
|
||||||
customMerge (param, fileId, count = 3) {
|
|
||||||
if (count === 0) return;
|
|
||||||
fileMerge(param).then(res => {
|
|
||||||
// 文件合并成功
|
|
||||||
Bus.$emit('fileSuccess');
|
|
||||||
|
|
||||||
this.statusRemove(fileId);
|
|
||||||
this.panelShow = false
|
|
||||||
Bus.$emit('refreshFileList'); // 触发刷新文件列表事件
|
|
||||||
}).catch(e => {
|
|
||||||
console.log("合并异常,重新发起请求,文件名为:", file.name)
|
|
||||||
//由于网络或服务器原因,导致合并过程中断线,此时如果不重新发起请求,就会进入失败的状态,导致该文件无法重试
|
|
||||||
this.customMerge(params, fileId, count - 1)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onFileError(rootFile, file, response, chunk) {
|
|
||||||
this.$message({
|
|
||||||
message: response,
|
|
||||||
type: 'error'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算md5,实现断点续传及秒传
|
|
||||||
* @param file
|
|
||||||
*/
|
|
||||||
computeMD5(file) {
|
|
||||||
let fileReader = new FileReader();
|
|
||||||
let time = new Date().getTime();
|
|
||||||
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
|
|
||||||
let currentChunk = 0;
|
|
||||||
const chunkSize = 10 * 1024 * 1000;
|
|
||||||
let chunks = Math.ceil(file.size / chunkSize);
|
|
||||||
let spark = new SparkMD5.ArrayBuffer();
|
|
||||||
|
|
||||||
// 文件状态设为"计算MD5"
|
|
||||||
this.statusSet(file.id, 'md5');
|
|
||||||
file.pause();
|
|
||||||
|
|
||||||
loadNext();
|
|
||||||
|
|
||||||
fileReader.onload = (e => {
|
|
||||||
|
|
||||||
spark.append(e.target.result);
|
|
||||||
|
|
||||||
if (currentChunk < chunks) {
|
|
||||||
currentChunk++;
|
|
||||||
loadNext();
|
|
||||||
|
|
||||||
// 实时展示MD5的计算进度
|
|
||||||
this.$nextTick(() => {
|
|
||||||
$(`.myStatus_${file.id}`).text('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%')
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let md5 = spark.end();
|
|
||||||
this.computeMD5Success(md5, file);
|
|
||||||
console.log(`MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks} 大小:${file.size} 用时:${new Date().getTime() - time} ms`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
fileReader.onerror = function () {
|
|
||||||
this.error(`文件${file.name}读取出错,请检查该文件`)
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computeMD5Success(md5, file) {
|
|
||||||
// 将自定义参数直接加载uploader实例的opts上
|
|
||||||
Object.assign(this.uploader.opts, {
|
|
||||||
query: {
|
|
||||||
...this.params,
|
|
||||||
filename: file.name
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
file.uniqueIdentifier = md5;
|
|
||||||
file.resume();
|
|
||||||
this.statusRemove(file.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
fileListShow() {
|
|
||||||
let $list = $('#global-uploader .file-list');
|
|
||||||
|
|
||||||
if ($list.is(':visible')) {
|
|
||||||
$list.slideUp();
|
|
||||||
this.collapse = true;
|
|
||||||
} else {
|
|
||||||
$list.slideDown();
|
|
||||||
this.collapse = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.uploader.cancel();
|
|
||||||
|
|
||||||
this.panelShow = false;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 新增的自定义的状态: 'md5'、'transcoding'、'failed'
|
|
||||||
* @param id
|
|
||||||
* @param status
|
|
||||||
*/
|
|
||||||
statusSet(id, status) {
|
|
||||||
let statusMap = {
|
|
||||||
md5: {
|
|
||||||
text: '校验MD5',
|
|
||||||
bgc: '#fff'
|
|
||||||
},
|
|
||||||
merging: {
|
|
||||||
text: '合并中',
|
|
||||||
bgc: '#e2eeff'
|
|
||||||
},
|
|
||||||
transcoding: {
|
|
||||||
text: '转码中',
|
|
||||||
bgc: '#e2eeff'
|
|
||||||
},
|
|
||||||
failed: {
|
|
||||||
text: '上传失败',
|
|
||||||
bgc: '#e2eeff'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
|
||||||
$(`<p class="myStatus_${id}"></p>`).appendTo(`.file_${id} .uploader-file-status`).css({
|
|
||||||
'position': 'absolute',
|
|
||||||
'top': '0',
|
|
||||||
'left': '0',
|
|
||||||
'right': '0',
|
|
||||||
'bottom': '0',
|
|
||||||
'zIndex': '1',
|
|
||||||
'line-height': 'initial',
|
|
||||||
'backgroundColor': statusMap[status].bgc
|
|
||||||
}).text(statusMap[status].text);
|
|
||||||
})
|
|
||||||
},
|
|
||||||
statusRemove(id) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
$(`.myStatus_${id}`).remove();
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
error(msg) {
|
|
||||||
this.$notify({
|
|
||||||
title: '错误',
|
|
||||||
message: msg,
|
|
||||||
type: 'error',
|
|
||||||
duration: 2000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {},
|
|
||||||
destroyed() {
|
|
||||||
Bus.$off('openUploader');
|
|
||||||
},
|
|
||||||
components: {}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style>
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -1,7 +1,6 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import uploader from 'vue-simple-uploader'
|
|
||||||
|
|
||||||
import Element from 'element-ui'
|
import Element from 'element-ui'
|
||||||
import './assets/styles/element-variables.scss'
|
import './assets/styles/element-variables.scss'
|
||||||
|
@ -73,7 +72,6 @@ Vue.component('FragmentUpload', FragmentUpload)
|
||||||
Vue.use(directive)
|
Vue.use(directive)
|
||||||
Vue.use(plugins)
|
Vue.use(plugins)
|
||||||
Vue.use(VueMeta)
|
Vue.use(VueMeta)
|
||||||
Vue.use(uploader)
|
|
||||||
DictData.install()
|
DictData.install()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -158,10 +158,6 @@
|
||||||
<el-form-item label="标题名称" prop="titleName">
|
<el-form-item label="标题名称" prop="titleName">
|
||||||
<el-input v-model="form.titleName" placeholder="请输入标题名称" />
|
<el-input v-model="form.titleName" placeholder="请输入标题名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="分片上传" prop="titleName">
|
|
||||||
<FragmentUpload
|
|
||||||
:width=100 :height=100 />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="标题英文名称" prop="titleEnglish">
|
<el-form-item label="标题英文名称" prop="titleEnglish">
|
||||||
<el-input v-model="form.titleEnglish" placeholder="请输入标题英文名称" />
|
<el-input v-model="form.titleEnglish" placeholder="请输入标题英文名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user