refactor: 背景图片直接存储在服务器

refactor: 背景图片直接存储在服务器
This commit is contained in:
王嘉豪 2022-04-25 12:13:05 +08:00 committed by GitHub
parent dbb8a7a76d
commit f55749417d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 270 additions and 27 deletions

View File

@ -48,6 +48,7 @@ public class ShiroServiceImpl implements ShiroService {
filterChainDefinitionMap.put("/plugin/theme/themes", ANON);
filterChainDefinitionMap.put("/plugin/theme/items/**", ANON);
filterChainDefinitionMap.put("/plugin/view/types", ANON);
filterChainDefinitionMap.put("/static-resource/**", ANON);
// 验证链接
filterChainDefinitionMap.put("/api/link/validate**", ANON);

View File

@ -0,0 +1,26 @@
package io.dataease.commons.utils;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
public class FileUtils {
public static void createIfAbsent(@NonNull Path path) throws IOException {
Assert.notNull(path, "Path must not be null");
if (Files.notExists(path)) {
// Create directories
Files.createDirectories(path);
LogUtil.debug("Created directory: [{}]", path);
}
}
}

View File

@ -0,0 +1,54 @@
package io.dataease.commons.utils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.NonNull;
import org.springframework.util.Assert;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
public class StaticResourceUtils {
public static final String URL_SEPARATOR = "/";
private static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
public static String ensureBoth(@NonNull String string, @NonNull String bothfix) {
return ensureBoth(string, bothfix, bothfix);
}
public static String ensureBoth(@NonNull String string, @NonNull String prefix,
@NonNull String suffix) {
return ensureSuffix(ensurePrefix(string, prefix), suffix);
}
/**
* Ensures the string contain prefix.
*
* @param string string must not be blank
* @param prefix prefix must not be blank
* @return string contain prefix specified
*/
public static String ensurePrefix(@NonNull String string, @NonNull String prefix) {
Assert.hasText(string, "String must not be blank");
Assert.hasText(prefix, "Prefix must not be blank");
return prefix + StringUtils.removeStart(string, prefix);
}
/**
* Ensures the string contain suffix.
*
* @param string string must not be blank
* @param suffix suffix must not be blank
* @return string contain suffix specified
*/
public static String ensureSuffix(@NonNull String string, @NonNull String suffix) {
Assert.hasText(string, "String must not be blank");
Assert.hasText(suffix, "Suffix must not be blank");
return StringUtils.removeEnd(string, suffix) + suffix;
}
}

View File

@ -0,0 +1,52 @@
package io.dataease.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.io.File;
import java.util.concurrent.TimeUnit;
import static io.dataease.commons.utils.StaticResourceUtils.ensureBoth;
import static io.dataease.commons.utils.StaticResourceUtils.ensureSuffix;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
@Configuration
public class DeMvcConfig implements WebMvcConfigurer {
private static final String FILE_PROTOCOL = "file://";
public static final String FILE_SEPARATOR = File.separator;
public static final String USER_HOME = "/opt/dataease/data";
private static String WORK_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "static-resource" + FILE_SEPARATOR;
/**
* Upload prefix.
*/
private final static String UPLOAD_URL_PREFIX = "static-resource";
/**
* url separator.
*/
public static final String URL_SEPARATOR = "/";
/**
* Configuring static resource path
*
* @param registry registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String workDir = FILE_PROTOCOL + ensureSuffix(WORK_DIR, FILE_SEPARATOR);
String uploadUrlPattern = ensureBoth(UPLOAD_URL_PREFIX, URL_SEPARATOR) + "**";
registry.addResourceHandler(uploadUrlPattern)
.addResourceLocations(workDir);
}
}

View File

@ -0,0 +1,18 @@
package io.dataease.config.properties;
import lombok.Data;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
@Data
public class StaticResourceProperties {
/**
* Upload prefix.
*/
private String uploadUrlPrefix = "static-resource";
}

View File

@ -0,0 +1,28 @@
package io.dataease.controller.staticResource;
import io.dataease.service.staticResource.StaticResourceService;
import io.swagger.annotations.ApiOperation;
import org.pentaho.ui.xul.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
@RestController
@RequestMapping("/static/resource")
public class StaticResourceController {
@Resource
StaticResourceService staticResourceService;
@PostMapping("upload/{fileId}")
@ApiOperation("Uploads static file")
public void upload(@PathVariable("fileId") String fileId, @RequestPart("file") MultipartFile file) {
staticResourceService.upload(fileId,file);
}
}

View File

@ -0,0 +1,48 @@
package io.dataease.service.staticResource;
import io.dataease.commons.utils.FileUtils;
import io.dataease.commons.utils.LogUtil;
import io.dataease.exception.DataEaseException;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* Author: wangjiahao
* Date: 2022/4/24
* Description:
*/
@Service
public class StaticResourceService {
private final Path staticDir = Paths.get("/opt/dataease/data/static-resource/");
public void upload(String fileId,MultipartFile file) {
// check if the path is valid (not outside staticDir)
Assert.notNull(file, "Multipart file must not be null");
try {
String originName = file.getOriginalFilename();
String newFileName = fileId+originName.substring(originName.lastIndexOf("."),originName.length());
Path uploadPath = Paths.get(staticDir.toString(), newFileName);
// create dir is absent
FileUtils.createIfAbsent(Paths.get(staticDir.toString()));
Files.createFile(uploadPath);
file.transferTo(uploadPath);
} catch (IOException e) {
LogUtil.error("文件上传失败",e);
DataEaseException.throwException("文件上传失败");
} catch (Exception e){
DataEaseException.throwException(e);
}
}
}

View File

@ -0,0 +1,26 @@
import request from '@/utils/request'
import { uuid } from 'vue-uuid'
import store from '@/store'
export function uploadFile(fileId, file) {
const param = new FormData()
param.append('file', file.file)
return request({
url: '/static/resource/upload/' + fileId,
method: 'post',
headers: { 'Content-Type': 'multipart/form-data' },
data: param,
loading: false
})
}
export function uploadFileResult(file, callback) {
const fileId = uuid.v1()
const fileName = file.file.name
const newFileName = fileId + fileName.substr(fileName.lastIndexOf('.'), fileName.length)
const fileUrl = store.state.staticResourcePath + newFileName
uploadFile(fileId, file).then(() => {
callback(fileUrl)
})
}

View File

@ -109,7 +109,9 @@ const data = {
// 仪表板视图明细
panelViewDetailsInfo: {},
// 当前tab页内组件
curActiveTabInner: null
curActiveTabInner: null,
// static resource local path
staticResourcePath: '/static-resource/'
},
mutations: {
...animation.mutations,

View File

@ -64,7 +64,6 @@
:on-remove="handleRemove"
:http-request="upload"
:file-list="fileList"
:on-change="onChange"
>
<i class="el-icon-plus" />
</el-upload>
@ -108,9 +107,9 @@
import { queryBackground } from '@/api/background/background'
import BackgroundItem from '@/views/background/BackgroundItem'
import { mapState } from 'vuex'
import eventBus from '@/components/canvas/utils/eventBus'
import { deepCopy } from '@/components/canvas/utils/utils'
import { COLOR_PANEL } from '@/views/chart/chart/chart'
import { uploadFileResult } from '@/api/staticResource/staticResource'
export default {
name: 'Background',
@ -179,7 +178,7 @@ export default {
},
handleRemove(file, fileList) {
this.uploadDisabled = false
this.panel.imageUrl = null
this.curComponent.commonBackground.outerImage = null
this.fileList = []
this.commitStyle()
},
@ -187,16 +186,11 @@ export default {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
onChange(file, fileList) {
var _this = this
_this.uploadDisabled = true
const reader = new FileReader()
reader.onload = function() {
_this.curComponent.commonBackground.outerImage = reader.result
}
reader.readAsDataURL(file.raw)
},
upload(file) {
const _this = this
uploadFileResult(file, (fileUrl) => {
_this.curComponent.commonBackground.outerImage = fileUrl
})
// console.log('this is upload')
}

View File

@ -25,12 +25,11 @@
accept=".jpeg,.jpg,.png,.gif"
class="avatar-uploader"
list-type="picture-card"
:http-request="upload"
:class="{disabled:uploadDisabled}"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:http-request="upload"
:file-list="fileList"
:on-change="onChange"
>
<i class="el-icon-plus" />
</el-upload>
@ -51,6 +50,7 @@
import { mapState } from 'vuex'
import { deepCopy } from '@/components/canvas/utils/utils'
import { COLOR_PANEL } from '@/views/chart/chart/chart'
import { uploadFileResult } from '@/api/staticResource/staticResource'
export default {
name: 'BackgroundSelector',
@ -98,19 +98,13 @@ export default {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
onChange(file, fileList) {
var _this = this
_this.uploadDisabled = true
const reader = new FileReader()
reader.onload = function() {
_this.panel.imageUrl = reader.result
this.commitStyle()
}
this.$store.state.styleChangeTimes++
reader.readAsDataURL(file.raw)
},
upload(file) {
// console.log('this is upload')
const _this = this
uploadFileResult(file, (fileUrl) => {
_this.$store.state.styleChangeTimes++
_this.panel.imageUrl = fileUrl
_this.commitStyle()
})
}
}
}