Commit f40e14dc authored by frank.xa.zhang's avatar frank.xa.zhang

add attachment file upload function -- frank

parent dfffe2bc
package pwc.taxtech.atms.controller;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import pwc.taxtech.atms.common.message.ErrorMessage;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.navtree.NavTreeDto;
import pwc.taxtech.atms.exception.ApplicationException;
import pwc.taxtech.atms.organization.dpo.OrganizationDirectorDto;
import pwc.taxtech.atms.organization.dpo.OrganizationHKDto;
import pwc.taxtech.atms.organization.dpo.OrganizationShareholderDto;
......@@ -101,15 +105,55 @@ public class OrganizationHKController {
return organizationHKService.updateShareholder(organizationShareholder);
}
@RequestMapping(value = "updateDirectors" ,method=RequestMethod.POST)
public @ResponseBody OperationResultDto<Object> updateDirectors(@RequestBody List<OrganizationDirectorDto> organizationDirectorDtos){
@RequestMapping(value = "updateDirectors", method = RequestMethod.POST)
public @ResponseBody
OperationResultDto<Object> updateDirectors(@RequestBody List<OrganizationDirectorDto> organizationDirectorDtos) {
logger.info("POST /api/v1/orgHK/updateDirectors");
return organizationHKService.updateDirectors(organizationDirectorDtos);
}
@RequestMapping(value = "updateShareholders" ,method=RequestMethod.POST)
public @ResponseBody OperationResultDto<Object> updateShareholders(@RequestBody List<OrganizationShareholderDto> organizationShareholderDtos){
@RequestMapping(value = "updateShareholders", method = RequestMethod.POST)
public @ResponseBody
OperationResultDto<Object> updateShareholders(@RequestBody List<OrganizationShareholderDto> organizationShareholderDtos) {
logger.info("POST /api/v1/orgHK/updateShareholders");
return organizationHKService.updateShareholders(organizationShareholderDtos);
}
@RequestMapping(value = "upload", method = RequestMethod.POST)
public @ResponseBody
OperationResultDto<Object> uploadOrgAttach(@RequestParam(value = "file") CommonsMultipartFile[] files, @RequestParam(value = "entityId") String orgId) {
logger.info("POST /api/v1/orgHK/upload");
logger.debug("enter upload file method");
OperationResultDto<Object> resultDto = new OperationResultDto<>();
logger.debug("validate parameters");
if (files == null || files.length == 0) {
resultDto.setResult(false);
resultDto.setResultMsg(ErrorMessage.NoFile);
return resultDto;
}
for (CommonsMultipartFile file : files) {
if (file == null || file.getSize() <= 0) {
resultDto.setResult(false);
resultDto.setResultMsg(ErrorMessage.NoFile);
return resultDto;
}
}
logger.debug("validate entityId");
if (StringUtils.isEmpty(orgId) || !organizationHKService.checkOrgExist(orgId)) {
resultDto.setResult(false);
logger.warn("organization [{}] not exist", orgId);
resultDto.setResultMsg("organization " + orgId + " not exist");
return resultDto;
}
logger.debug("start upload");
try {
resultDto = organizationHKService.uploadAttachs(files, orgId);
} catch (ApplicationException ex) {
resultDto.setResult(false);
}
return resultDto;
}
}
package pwc.taxtech.atms.service.impl;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Pattern;
@Component
public class OrgHKUtil {
// 定义日期的范围,暂定为2000年到8000年
static final long minTime;
static final long maxTime;
static {
SimpleDateFormat sdf = buildDateFormatStatic("yyyy");
try {
minTime = sdf.parse("2000").getTime();
maxTime = sdf.parse("8000").getTime();
} catch (ParseException e) {
throw Lang.wrapThrow(e);
}
}
/** 字符串转日期格式,如果出错返回null */
public Date stringToDate(String inputString, String dateformat) {
try {
SimpleDateFormat sdf = buildDateFormat(dateformat);
Date result = sdf.parse(inputString);
Assert.notNull(result, "Null result date");
// 查看是否是合法的范围
// 因为Sqlserver数据库的datetime范围是有限的
if (result.getTime() >= minTime && result.getTime() <= maxTime)
return result;
if (dateformat.contains("yyyy")) {
// 尝试把4位年份改为2位的再转一次
return stringToDate(inputString, dateformat.replace("yyyy", "yy"));
} else {
return null;
}
} catch (Exception e) {
return null;
}
}
/**
* 构造一个SimpleDateFormat对象,使用上海时区
*
* @exception NullPointerException
* if the given pattern is null
*
* @exception IllegalArgumentException
* if the given pattern is invalid
*/
public SimpleDateFormat buildDateFormat(String dateformat) {
return buildDateFormatStatic(dateformat);
}
private static SimpleDateFormat buildDateFormatStatic(String dateformat) {
SimpleDateFormat sdf = new SimpleDateFormat(dateformat, Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
return sdf;
}
/** Trim字符串,并限定字符串的长度. 如果是输入值是空指针,会返回空字符串 */
public String trimLimit(String str, int limit) {
if (Strings.isBlank(str)) {
return "";
}
String tmp = str.trim();
String result = cutString(tmp, limit);
if (result == null)
result = "";
return result;
}
/** 限定字符串的长度. */
public String cutString(String s, int length) {
if (Lang.isEmpty(length) || Lang.isEmpty(s))
return "";
else if (s.length() <= length)
return s;
else
return s.substring(0, length);
}
/** 把字符串转为金额,支逗号做小数点, 如果格式出错返回null */
private BigDecimal toAmount(String str) {
String tmp = trimLimit(str, 100);
if (Strings.isBlank(str)) {
return null;
}
try {
tmp = tmp.replaceAll(",", "");
return new BigDecimal(tmp);
} catch (Exception e) {
return null;
}
}
public BigDecimal toAmount(String str, boolean germanyStyleFlag) {
if (germanyStyleFlag)
return toAmountGermanyStyle(str);
return toAmount(str);
}
/** 把字符串转为金额,支逗号做小数点, 如果格式出错返回null. */
private BigDecimal toAmountGermanyStyle(String str) {
String tmp = trimLimit(str, 100);
if (Strings.isBlank(str)) {
return null;
}
try {
tmp = tmp.replaceAll("\\.", "").replaceAll(",", ".");
return new BigDecimal(tmp);
} catch (Exception e) {
return null;
}
}
/**
* 字符窜千分位会用逗号分割转换
* "12,958.20" to "12958.20"
* @param str
* @param germanyStyleFlag
* @return
*/
public BigDecimal toAmountThounsands(String str, boolean germanyStyleFlag) {
if (germanyStyleFlag)
return toAmountGermanyStyleThounsands(str);
return toAmount(str);
}
/** 把字符串转为金额,去除逗号,小数点保留, 如果格式出错返回null. */
private BigDecimal toAmountGermanyStyleThounsands(String str) {
String tmp = trimLimit(str, 100);
if (Strings.isBlank(str)) {
return null;
}
try {
tmp = tmp.replaceAll(",", "");
return new BigDecimal(tmp);
} catch (Exception e) {
return null;
}
}
/** 去除字符串中的空格, 比如"40.00 %"转为"40.00%" */
public String replaceSpace(String str, int limit) {
if (Strings.isBlank(str)) {
return "";
}
return trimLimit(str.replaceAll("\\s+", ""), limit);
}
/** 去除字母等非数字部份,只取数字部份,但会保留小数点,逗号 */
public String cleanAmountString(String str) {
if (Strings.isBlank(str)) {
return "";
}
String tmp = trimLimit(str, 100);
Pattern p = Pattern.compile("[^0-9,.]+");
return p.matcher(tmp).replaceAll("");
}
/** 去除字母等非数字部份,只取数字部份,但会保留小数点,逗号 */
public String cleanAmountString(String str, int limit) {
if (Strings.isBlank(str)) {
return "";
}
String tmp = trimLimit(str, limit);
Pattern p = Pattern.compile("[^0-9,.]+");
return p.matcher(tmp).replaceAll("");
}
/** 去除文件名里的中文,特殊字符等,只保留a-zA-Z.0-9_- */
public String cleanFilename(String str) {
if (Strings.isBlank(str)) {
return "";
}
String tmp = trimLimit(str, 100);
Pattern p = Pattern.compile("[^a-zA-Z.0-9_\\-]+");
return p.matcher(tmp).replaceAll("");
}
public String BigDecimalToString(BigDecimal input, String format) {
if (input == null)
return "";
try {
DecimalFormat df = new DecimalFormat(format);
return df.format(input);
} catch (Exception e) {
return String.valueOf(input);
}
}
/** 使用######.##来格式化 */
public String BigDecimalToString(BigDecimal input) {
return BigDecimalToString(input, "######.##");
}
public String getChinese(String paramValue) {
if (Strings.isBlank(paramValue)) {
return "";
}
return paramValue.replaceAll("[^\u4e00-\u9fa5]", "");
}
/**
* 数字转为26进制
* <pre>
0 -> A
1 -> B
2 -> C
...
25 -> Z
26 -> AA
27 -> AB
28 -> AC
...
701 -> ZZ
702 -> AAA
...
* </pre>
*/
public String toAlphabetic(int i) {
if (i < 0) {
return "-" + toAlphabetic(-i - 1);
}
int quot = i / 26;
int rem = i % 26;
char letter = (char) ((int) 'A' + rem);
if (quot == 0) {
return "" + letter;
} else {
return toAlphabetic(quot - 1) + letter;
}
}
}
package pwc.taxtech.atms.service.impl;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.nutz.lang.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import pwc.taxtech.atms.common.*;
import pwc.taxtech.atms.common.message.LogMessage;
import pwc.taxtech.atms.common.message.OrganizationMessage;
import pwc.taxtech.atms.common.util.BeanUtil;
import pwc.taxtech.atms.dto.OperationLogDto;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.UpdateLogParams;
import pwc.taxtech.atms.dto.navtree.NavTreeDto;
import pwc.taxtech.atms.entity.ServiceType;
import pwc.taxtech.atms.exception.ApplicationException;
import pwc.taxtech.atms.organization.dao.OrganizationAttachmentMapper;
import pwc.taxtech.atms.organization.dao.OrganizationDirectorMapper;
import pwc.taxtech.atms.organization.dao.OrganizationHKMapper;
import pwc.taxtech.atms.organization.dao.OrganizationShareholderMapper;
......@@ -26,6 +32,8 @@ import pwc.taxtech.atms.organization.dpo.OrganizationShareholderDto;
import pwc.taxtech.atms.organization.entity.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
......@@ -58,7 +66,16 @@ public class OrganizationHKServiceImpl {
private AuthUserHelper authUserHelper;
@Autowired
private BeanUtil beanUtil;
private OrgHKUtil orgHKUtil;
@Autowired
private FileService fileService;
@Resource
private OrganizationAttachmentMapper organizationAttachmentMapper;
@Value("${orgaization.file.location}")
private String fileDirectory;
public List<OrganizationHKDto> getOrgInfo() {
List<OrganizationHKDto> organizationHKDtos = new ArrayList<>();
......@@ -469,4 +486,102 @@ public class OrganizationHKServiceImpl {
resultDto.setResult(true);
return resultDto;
}
public boolean checkOrgExist(String orgId) {
OrganizationHKExample example = new OrganizationHKExample();
example.createCriteria().andIdEqualTo(Long.parseLong(orgId)).andIsActiveEqualTo(true);
List<OrganizationHK> organizationHKs = organizationHKMapper.selectByExample(example);
return organizationHKs != null && organizationHKs.size() > 0;
}
public OperationResultDto<Object> uploadAttachs(CommonsMultipartFile[] files, String orgId) {
logger.debug("OrganizationHKServiceImpl uploadAttachs start");
OperationResultDto<Object> result = new OperationResultDto<>();
List<OrganizationAttachment> organizationAttachments = new ArrayList<>();
for (CommonsMultipartFile file : files) {
final String orginalName = file.getOriginalFilename();
logger.debug("orgianal file name[{}]", orginalName);
Assert.notNull(orginalName, "null orginal file name");
Assert.state(orginalName.length() <= 500, "invalid file name length for file: " + orginalName.length());
if (!fileDirectory.endsWith("/")) {
fileDirectory = fileDirectory + "/";
}
final Date now = new Date();
final String pathYearMonth = orgHKUtil.buildDateFormat("yyyy/MM").format(now);
final String fileNameYearMonthDay = orgHKUtil.buildDateFormat("yyyyMMdd").format(now);
// fileNameWithoutExtension:对文件名做处理,删除特殊字符,限制长度为50
final String fileNameWithoutExtension = orgHKUtil
.trimLimit(orgHKUtil.cleanFilename(FilenameUtils.getBaseName(orginalName)), 50);
final String fileExtension = FilenameUtils.getExtension(orginalName).toLowerCase();
final String fileNameToSave = (fileNameYearMonthDay + "_" + fileNameWithoutExtension + "_"
+ CommonUtils.getUUID().substring(0, 6) + "." + fileExtension).toLowerCase();
// relatedDirectory:相对路径目录,以/结尾
final String relatedDirectory = pathYearMonth + "/" + "organization attachments" + "/";
// generatedFileDirectory:绝对路径目录
final String generatedFileDirectory = fileDirectory + relatedDirectory;
logger.debug("create file directory does not exist, directory: {}", generatedFileDirectory);
Files.createDirIfNoExists(generatedFileDirectory);
String filePath = generatedFileDirectory + fileNameToSave;
final String filePathToSave = relatedDirectory + fileNameToSave;
logger.debug("file path: {}", filePath);
logger.debug("save file in file system");
OperationResultDto<Object> saveResult = saveAttachFile(file, filePath);
// if save failed, should roll back all changes
if (saveResult.getResult() == null || !saveResult.getResult()) {
throw new ApplicationException("failed to save file in file system");
}
logger.debug("save file in database");
OrganizationAttachment organizationAttachment = saveOrgAttachments(filePath, filePathToSave, fileNameToSave, orgId, file, fileExtension);
organizationAttachments.add(organizationAttachment);
}
if (CollectionUtils.isEmpty(organizationAttachments)) {
logger.debug("output file is empty");
result.setResult(false);
result.setResultMsg("output file is empty");
return result;
}
result.setResult(true);
logger.debug("output file size: {}", organizationAttachments.size());
logger.debug("OrganizationHKServiceImpl uploadAttachs end");
return result;
}
private OrganizationAttachment saveOrgAttachments(String filePath, String filePathToSave, String fileNameToSave, String orgId, CommonsMultipartFile file, String fileExtension) {
OrganizationAttachment organizationAttachment = new OrganizationAttachment();
organizationAttachment.setId(distributedIdService.nextId());
organizationAttachment.setEntityId(Long.valueOf(orgId));
organizationAttachment.setCalendarEventId(0L);
organizationAttachment.setCalendarConfigId(0L);
organizationAttachment.setDocumentName(fileNameToSave);
organizationAttachment.setDocumentPath(filePathToSave);
organizationAttachment.setDocumentExtension(fileExtension);
Date now = new Date();
organizationAttachment.setCreateTime(now);
organizationAttachment.setUpdateTime(now);
organizationAttachment.setCreateBy(authUserHelper.getCurrentUserId());
organizationAttachment.setUpdateBy(authUserHelper.getCurrentUserId());
organizationAttachmentMapper.insertSelective(organizationAttachment);
return organizationAttachment;
}
private OperationResultDto<Object> saveAttachFile(CommonsMultipartFile inputFile, String filePath) {
InputStream inputStream;
try {
inputStream = inputFile.getInputStream();
} catch (IOException e) {
throw new ApplicationException(e.getMessage());
}
OperationResultDto<Object> saveResult = fileService.saveFile(inputStream, filePath);
return saveResult;
}
}
......@@ -700,10 +700,93 @@
$scope.selectCompany = {};
};
$scope.uploadAttach = function () {
var token = $('input[name="__RequestVerificationToken"]').val();
$scope.uploadFiles = function (files, errFiles) {
$scope.f = files;
$scope.showError = false;
$scope.errFile = errFiles && errFiles[0];
if (files && files.length) {
var fileNames = [];
angular.forEach($scope.f, function (file) {
fileNames.push(file.name);
});
$scope.filePath = fileNames.toString();//$scope.f[0].name;
if (!checkUploadFiles($scope.f)) {
return false;
}
Upload.upload({
url: webHost + ' /api/v1/orgHK/upload',
data: {
entityId: $scope.selectCompany.id,
file: files
},
headers: {
'Access-Control-Allow-Origin': '*',
Authorization: apiTokenObj.token_type + ' ' + apiTokenObj.access_token,
from: ''
},
__RequestVerificationToken: token,
withCredentials: true
}).then(function (response) {
console.log(response);
var ret = response.data;
if (ret.result) {
//todo: need add the result data to exist attachments files list
}
else {
if (ret.resultMsg && ret.resultMsg.length > 0) {
swal({
title: $translate.instant('FailureTitle'),
text: $translate.instant('UploadFileFail') + ret.resultMsg,
type: "error",
confirmButtonText: $translate.instant('Confirm')
});
}
}
}, function (response) {
console.log('import error: ' + response.status);
if (response.status > 0) {
$log.debug('upload attach file error:');
$log.debug(response.status + ': ' + response.data);
}
}, function (evt) {
$scope.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
});
}
else {
}
};
function checkUploadFiles(files) {
var result = true;
for (var i = 0; i < files.length; i++) {
var item = files[i];
var fileName = item.name;
var fileExtension = fileName.substr(fileName.lastIndexOf(".") + 1, fileName.length - fileName.lastIndexOf(".")).toLowerCase();
if (fileExtension !== ValidFileExtension.CSV
&& fileExtension !== ValidFileExtension.XLS
&& fileExtension !== ValidFileExtension.XLSX) {
swal({
title: $translate.instant('WarningTitle'),
text: $translate.instant('ErpUploadFileExtensionCheck'),
type: "warning",
confirmButtonText: $translate.instant('Confirm')
});
result = false;
}
if (fileName.length >= 30) {
SweetAlert.warning($translate.instant('FileNameTooLong'));
result = false;
}
}
return result;
}
$scope.exportOrgs = function () {
};
......
......@@ -292,8 +292,8 @@
<span style="font-size: large;font-weight: bold">Attachment</span>
</div>
<div class="attachment-option">
<button type="button" id="uploadAttachBtn" class="btn" ng-click="uploadAttach()"
style="float:right;background: transparent;">
<button id="uploadAttachBtn" class="btn" style="float:right;background: transparent;" type="file"
multiple="" ngf-select="uploadFiles($files, $invalidFiles)" accept="*" ngf-max-height="1000" ngf-max-size="20MB">
<i class="fa fa-upload" aria-hidden="true" style="font-size: large"></i>{{'upload'|translate}}
</button>
</div>
......@@ -386,8 +386,10 @@
<operate-log is-show="isShowLog"></operate-log>
<edit-organization-modal is-show="showEditModal" parent-page=".system-manage" operate-type="orgOperateType" is-update="isOrgUpdate" selected-organization="selectedOrg"></edit-organization-modal>
<edit-organization-shareholder-modal is-show-s="isShowShareholderModal2" parent-page=".system-manage" edit-model-s="gModel.editShareholderModel" on-close="closeSharehoder2()" on-save="saveShareholder2(shareholderEntity)"></edit-organization-shareholder-modal>
<edit-organization-director-modal is-show-d="isShowDirectorModal2" parent-page=".system-manage" edit-model-d="gModel.editDirectorModel" on-close="closeDirector2()" on-save="saveDirector2(directorEntity)"></edit-organization-director-modal>
<edit-organization-shareholder-modal is-show-s="isShowShareholderModal2" parent-page=".system-manage" edit-model-s="gModel.editShareholderModel" on-close="closeSharehoder2()"
on-save="saveShareholder2(shareholderEntity)"></edit-organization-shareholder-modal>
<edit-organization-director-modal is-show-d="isShowDirectorModal2" parent-page=".system-manage" edit-model-d="gModel.editDirectorModel" on-close="closeDirector2()"
on-save="saveDirector2(directorEntity)"></edit-organization-director-modal>
<!--<edit-equity-modal operate-type="equityEditOperateType" is-update="isEquityUpdate"-->
<!--selected-organization="selectedOrg"></edit-equity-modal>-->
<!--<edit-equity-change-modal operate-type="equityChangeOperateType" is-update="isEquityChange"-->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment