diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/Application.java b/contact-center/app/src/main/java/com/chatopera/cc/app/Application.java index 60e6e8f0..00b84c4a 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/app/Application.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/Application.java @@ -36,6 +36,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.servlet.MultipartConfigElement; import java.io.IOException; @@ -44,6 +45,7 @@ import java.io.IOException; @EnableJpaRepositories("com.chatopera.cc.app.persistence.repository") @EnableElasticsearchRepositories("com.chatopera.cc.app.persistence.es") @EnableAsync +@EnableTransactionManagement public class Application { @Value("${web.upload-path}") diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/basic/MainUtils.java b/contact-center/app/src/main/java/com/chatopera/cc/app/basic/MainUtils.java index e98cbd60..75de78ba 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/app/basic/MainUtils.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/basic/MainUtils.java @@ -766,14 +766,14 @@ public class MainUtils { return workintTime; } - public static File processImage(File destFile, File imageFile) throws FileNotFoundException, IOException { + public static File processImage(final File destFile, final File imageFile) throws FileNotFoundException, IOException { if (imageFile != null && imageFile.exists()) { Thumbnails.of(imageFile).width(460).keepAspectRatio(true).toFile(destFile); } return destFile; } - public static File scaleImage(File destFile, File imageFile, float quality) throws FileNotFoundException, IOException { + public static File scaleImage(final File destFile, final File imageFile, float quality) throws FileNotFoundException, IOException { if (imageFile != null && imageFile.exists()) { Thumbnails.of(imageFile).scale(1f).outputQuality(quality).toFile(destFile); } @@ -846,45 +846,6 @@ public class MainUtils { return execute; } - public static void processAttachmentFile(MultipartFile[] files, AttachmentRepository attachementRes, String path, User user, String orgi, WorkOrders workOrders, HttpServletRequest request, String dataid, String modelid) throws IOException { - if (files != null && files.length > 0) { - workOrders.setAnonymous(true);//变更用途为是否有 附件 - //保存附件 - for (MultipartFile file : files) { - if (file.getSize() > 0) { //文件尺寸 限制 ?在 启动 配置中 设置 的最大值,其他地方不做限制 - String fileid = MainUtils.md5(file.getBytes()); //使用 文件的 MD5作为 ID,避免重复上传大文件 - if (!StringUtils.isBlank(fileid)) { - AttachmentFile attachmentFile = new AttachmentFile(); - attachmentFile.setCreater(user.getId()); - attachmentFile.setOrgi(orgi); - attachmentFile.setOrgan(user.getOrgan()); - attachmentFile.setDataid(dataid); - attachmentFile.setModelid(modelid); - attachmentFile.setModel(MainContext.ModelType.WORKORDERS.toString()); - attachmentFile.setFilelength((int) file.getSize()); - if (file.getContentType() != null && file.getContentType().length() > 255) { - attachmentFile.setFiletype(file.getContentType().substring(0, 255)); - } else { - attachmentFile.setFiletype(file.getContentType()); - } - if (file.getOriginalFilename() != null && file.getOriginalFilename().length() > 255) { - attachmentFile.setTitle(file.getOriginalFilename().substring(0, 255)); - } else { - attachmentFile.setTitle(file.getOriginalFilename()); - } - if (!StringUtils.isBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) { - attachmentFile.setImage(true); - } - attachmentFile.setFileid(fileid); - attachementRes.save(attachmentFile); - FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes()); - } - } - } - - } - } - /** * 获取系统配置 * diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/agent/AgentController.java b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/agent/AgentController.java index b4e4025a..70ff8b17 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/agent/AgentController.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/agent/AgentController.java @@ -25,15 +25,13 @@ import com.chatopera.cc.app.im.client.NettyClients; import com.chatopera.cc.app.im.message.ChatMessage; import com.chatopera.cc.app.im.router.OutMessageRouter; import com.chatopera.cc.app.model.*; +import com.chatopera.cc.app.persistence.blob.JpaBlobHelper; import com.chatopera.cc.app.persistence.es.ContactsRepository; import com.chatopera.cc.app.persistence.es.QuickReplyRepository; import com.chatopera.cc.app.persistence.repository.*; import com.chatopera.cc.exception.CSKefuException; import com.chatopera.cc.exchange.DataExchangeInterface; -import com.chatopera.cc.util.Menu; -import com.chatopera.cc.util.OnlineUserUtils; -import com.chatopera.cc.util.PinYinTools; -import com.chatopera.cc.util.PropertiesEventUtils; +import com.chatopera.cc.util.*; import com.chatopera.cc.util.mobile.MobileAddress; import com.chatopera.cc.util.mobile.MobileNumberUtils; import freemarker.template.TemplateException; @@ -149,6 +147,12 @@ public class AgentController extends Handler { @Autowired private ConsultInviteRepository inviteRepository; + @Autowired + private StreamingFileRepository streamingFileRepository; + + @Autowired + private JpaBlobHelper jpaBlobHelper; + @Value("${web.upload-path}") private String path; @@ -169,7 +173,7 @@ public class AgentController extends Handler { } } } - if (!StringUtils.isBlank(sort)) { + if (StringUtils.isNotBlank(sort)) { List list = new ArrayList(); if (sort.equals("lastmessage")) { list.add(new Order(Direction.DESC, "status")); @@ -208,7 +212,7 @@ public class AgentController extends Handler { agentUser = (AgentUser) agentUserList.get(0); view.addObject("curagentuser", agentUser); view.addObject("inviteData", OnlineUserUtils.cousult(agentUser.getAppid(), agentUser.getOrgi(), inviteRepository)); - if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { List summarizes = this.serviceSummaryRes.findByAgentserviceidAndOrgi(agentUser.getAgentserviceid(), super.getOrgi(request)); if (summarizes.size() > 0) { view.addObject("summary", summarizes.get(0)); @@ -217,7 +221,7 @@ public class AgentController extends Handler { view.addObject("agentUserMessageList", this.chatMessageRepository.findByUsessionAndOrgi(agentUser.getUserid(), super.getOrgi(request), new PageRequest(0, 20, Direction.DESC, "updatetime"))); AgentService agentService = null; - if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { agentService = this.agentServiceRepository.findOne(agentUser.getAgentserviceid()); view.addObject("curAgentService", agentService); @@ -247,10 +251,10 @@ public class AgentController extends Handler { view.addObject("onlineUser", onlineUser); } } else if (MainContext.ChannelTypeEnum.PHONE.toString().equals(agentUser.getChannel())) { - if (agentService != null && !StringUtils.isBlank(agentService.getOwner())) { + if (agentService != null && StringUtils.isNotBlank(agentService.getOwner())) { StatusEvent statusEvent = this.statusEventRes.findById(agentService.getOwner()); if (statusEvent != null) { - if (!StringUtils.isBlank(statusEvent.getHostid())) { + if (StringUtils.isNotBlank(statusEvent.getHostid())) { PbxHost pbxHost = pbxHostRes.findById(statusEvent.getHostid()); view.addObject("pbxHost", pbxHost); } @@ -302,19 +306,19 @@ public class AgentController extends Handler { ) ); - if (!StringUtils.isBlank(agentService.getAppid())) { + if (StringUtils.isNotBlank(agentService.getAppid())) { map.addAttribute("snsAccount", snsAccountRes.findBySnsidAndOrgi(agentService.getAppid(), super.getOrgi(request))); } List relaList = agentUserContactsRes.findByUseridAndOrgi(agentService.getUserid(), agentService.getOrgi()); if (relaList.size() > 0) { AgentUserContacts agentUserContacts = relaList.get(0); - if (MainContext.model.get("contacts") != null && !StringUtils.isBlank(agentUserContacts.getContactsid())) { + if (MainContext.model.get("contacts") != null && StringUtils.isNotBlank(agentUserContacts.getContactsid())) { DataExchangeInterface dataExchange = (DataExchangeInterface) MainContext.getContext().getBean("contacts"); if (dataExchange != null) { map.addAttribute("contacts", dataExchange.getDataByIdAndOrgi(agentUserContacts.getContactsid(), super.getOrgi(request))); } } - if (MainContext.model.get("workorders") != null && !StringUtils.isBlank(agentUserContacts.getContactsid())) { + if (MainContext.model.get("workorders") != null && StringUtils.isNotBlank(agentUserContacts.getContactsid())) { DataExchangeInterface dataExchange = (DataExchangeInterface) MainContext.getContext().getBean("workorders"); if (dataExchange != null) { map.addAttribute("workOrdersList", dataExchange.getListDataByIdAndOrgi(agentUserContacts.getContactsid(), super.getUser(request).getId(), super.getOrgi(request))); @@ -346,7 +350,7 @@ public class AgentController extends Handler { agentUserTaskRes.save(agentUserTask); } - if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { List summarizes = this.serviceSummaryRes.findByAgentserviceidAndOrgi(agentUser.getAgentserviceid(), super.getOrgi(request)); if (summarizes.size() > 0) { view.addObject("summary", summarizes.get(0)); @@ -355,7 +359,7 @@ public class AgentController extends Handler { view.addObject("agentUserMessageList", this.chatMessageRepository.findByUsessionAndOrgi(agentUser.getUserid(), super.getOrgi(request), new PageRequest(0, 20, Direction.DESC, "updatetime"))); AgentService agentService = null; - if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { agentService = this.agentServiceRepository.findOne(agentUser.getAgentserviceid()); view.addObject("curAgentService", agentService); if (agentService != null) { @@ -385,10 +389,10 @@ public class AgentController extends Handler { view.addObject("onlineUser", onlineUser); } } else if (MainContext.ChannelTypeEnum.PHONE.toString().equals(agentUser.getChannel())) { - if (agentService != null && !StringUtils.isBlank(agentService.getOwner())) { + if (agentService != null && StringUtils.isNotBlank(agentService.getOwner())) { StatusEvent statusEvent = this.statusEventRes.findById(agentService.getOwner()); if (statusEvent != null) { - if (!StringUtils.isBlank(statusEvent.getHostid())) { + if (StringUtils.isNotBlank(statusEvent.getHostid())) { PbxHost pbxHost = pbxHostRes.findById(statusEvent.getHostid()); view.addObject("pbxHost", pbxHost); } @@ -455,7 +459,7 @@ public class AgentController extends Handler { @RequestMapping("/workorders/list") @Menu(type = "apps", subtype = "workorderslist") public ModelAndView workorderslist(HttpServletRequest request, String contactsid, ModelMap map) { - if (MainContext.model.get("workorders") != null && !StringUtils.isBlank(contactsid)) { + if (MainContext.model.get("workorders") != null && StringUtils.isNotBlank(contactsid)) { DataExchangeInterface dataExchange = (DataExchangeInterface) MainContext.getContext().getBean("workorders"); if (dataExchange != null) { map.addAttribute("workOrdersList", dataExchange.getListDataByIdAndOrgi(contactsid, super.getUser(request).getId(), super.getOrgi(request))); @@ -481,7 +485,7 @@ public class AgentController extends Handler { agentStatus.setAgentno(user.getId()); agentStatus.setLogindate(new Date()); - if (!StringUtils.isBlank(user.getOrgan())) { + if (StringUtils.isNotBlank(user.getOrgan())) { Organ organ = organRes.findByIdAndOrgi(user.getOrgan(), super.getOrgiByTenantshare(request)); if (organ != null && organ.isSkill()) { agentStatus.setSkill(organ.getId()); @@ -589,7 +593,7 @@ public class AgentController extends Handler { AgentUser agentUser = agentUserRepository.findByIdAndOrgi(userid, super.getOrgi(request)); if (agentUser != null && super.getUser(request).getId().equals(agentUser.getAgentno())) { AutomaticServiceDist.deleteAgentUser(agentUser, super.getOrgi(request)); - if (!StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) { AgentService agentService = agentServiceRepository.findByIdAndOrgi(agentUser.getAgentserviceid(), super.getOrgi(request)); agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString()); agentServiceRepository.save(agentService); @@ -655,7 +659,7 @@ public class AgentController extends Handler { blackListRes.save(tempBlackEntiry); blackEntity = tempBlackEntiry; } - if (!StringUtils.isBlank(userid)) { + if (StringUtils.isNotBlank(userid)) { CacheHelper.getSystemCacheBean().put(userid, blackEntity, super.getOrgi(request)); } } @@ -681,58 +685,58 @@ public class AgentController extends Handler { @RequestMapping("/image/upload") @Menu(type = "im", subtype = "image", access = false) - public ModelAndView upload(ModelMap map, HttpServletRequest request, @RequestParam(value = "imgFile", required = false) MultipartFile imgFile, @Valid String id, @Valid String paste) throws IOException { + public ModelAndView upload(ModelMap map, + HttpServletRequest request, + @RequestParam(value = "imgFile", required = false) MultipartFile multipart, + @Valid String id, + @Valid String paste) throws IOException { ModelAndView view = request(super.createRequestPageTempletResponse("/apps/agent/upload")); - UploadStatus upload = null; - String fileName = null; - if (imgFile != null && imgFile.getOriginalFilename().lastIndexOf(".") > 0) { + UploadStatus notify = null; + if (multipart != null && multipart.getOriginalFilename().lastIndexOf(".") > 0) { File uploadDir = new File(path, "upload"); if (!uploadDir.exists()) { uploadDir.mkdirs(); } - String fileid = MainUtils.md5(imgFile.getBytes()), fileURL = null, targetFile = null; + String fileid = MainUtils.getUUID(); + String fileURL = null; ChatMessage data = new ChatMessage(); - if (imgFile.getContentType() != null && imgFile.getContentType().indexOf("image") >= 0) { - fileName = "upload/" + fileid + "_original"; - File imageFile = new File(path, fileName); - FileCopyUtils.copy(imgFile.getBytes(), imageFile); - targetFile = "upload/" + fileid; - MainUtils.processImage(new File(path, targetFile), imageFile); + StreamingFile sf = new StreamingFile(); - - fileURL = "/res/image.html?id=" + targetFile; - if (request.getServerPort() == 80) { - fileURL = "/res/image.html?id=" + targetFile; - } else { - fileURL = "/res/image.html?id=" + targetFile; - } - upload = new UploadStatus("0", fileURL); //图片直接发送给 客户,不用返回 - data.setAttachmentid(fileid); + if (multipart.getContentType() != null && multipart.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) { + // process thumbnail + File original = new File(path, "upload/" + fileid + "_original"); + File thumbnail = new File(path, "upload/" + fileid); + FileCopyUtils.copy(multipart.getBytes(), original); + MainUtils.processImage(thumbnail, original); + sf.setThumbnail(jpaBlobHelper.createBlobWithFile(thumbnail)); + fileURL = "/res/image.html?id=" + fileid; } else { - String attachid = processAttachmentFile(imgFile, request); - - upload = new UploadStatus("0", "/res/file.html?id=" + attachid); + String attachid = processAttachmentFile(multipart, fileid, request); fileURL = "/res/file.html?id=" + attachid; - if (request.getServerPort() == 80) { - fileURL = "/res/file.html?id=" + attachid; - } else { - fileURL = "/res/file.html?id=" + attachid; - } } - data.setFilename(imgFile.getOriginalFilename()); - data.setFilesize((int) imgFile.getSize()); - OutMessageRouter router = null; + sf.setId(fileid); + sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize())); + sf.setName(multipart.getOriginalFilename()); + sf.setMime(multipart.getContentType()); + streamingFileRepository.save(sf); + + data.setFilename(multipart.getOriginalFilename()); + data.setFilesize((int) multipart.getSize()); + data.setAttachmentid(fileid); + + notify = new UploadStatus("0", fileURL); + AgentUser agentUser = agentUserRepository.findByIdAndOrgi(id, super.getOrgi(request)); - if (agentUser != null && paste == null) { - router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); + if (agentUser != null && paste == null) { // 发送消息 + OutMessageRouter router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); MessageOutContent outMessage = new MessageOutContent(); - if (router != null) { + if (router != null) { // 发送消息给访客 outMessage.setMessage(fileURL); - outMessage.setFilename(imgFile.getOriginalFilename()); - outMessage.setFilesize((int) imgFile.getSize()); - if (imgFile.getContentType() != null && imgFile.getContentType().indexOf("image") >= 0) { + outMessage.setFilename(multipart.getOriginalFilename()); + outMessage.setFilesize((int) multipart.getSize()); + if (multipart.getContentType() != null && multipart.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) { outMessage.setMessageType(MainContext.MediaTypeEnum.IMAGE.toString()); data.setMsgtype(MainContext.MediaTypeEnum.IMAGE.toString()); } else { @@ -753,7 +757,7 @@ public class AgentController extends Handler { data.setAgentserviceid(agentUser.getAgentserviceid()); data.setCalltype(MainContext.CallTypeEnum.OUT.toString()); - if (!StringUtils.isBlank(agentUser.getAgentno())) { + if (StringUtils.isNotBlank(agentUser.getAgentno())) { data.setTouser(agentUser.getUserid()); } data.setChannel(agentUser.getChannel()); @@ -771,11 +775,10 @@ public class AgentController extends Handler { // 通知文件上传消息 NettyClients.getInstance().publishAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.MESSAGE.toString(), data); } - } else { - upload = new UploadStatus("请选择图片文件"); + notify = new UploadStatus("请选择图片文件"); } - map.addAttribute("upload", upload); + map.addAttribute("upload", notify); return view; } @@ -785,7 +788,7 @@ public class AgentController extends Handler { ChatMessage message = chatMessageRepository.findById(id); map.addAttribute("chatMessage", message); map.addAttribute("agentUser", CacheHelper.getAgentUserCacheBean().getCacheObject(message.getUserid(), message.getOrgi())); - /*if(!StringUtils.isBlank(t)){ + /*if(StringUtils.isNotBlank(t)){ map.addAttribute("t", t) ; }*/ map.addAttribute("t", true); @@ -794,22 +797,37 @@ public class AgentController extends Handler { @RequestMapping("/message/image/upload") @Menu(type = "im", subtype = "image", access = false) - public ModelAndView messageimage(ModelMap map, HttpServletRequest request, @RequestParam(value = "image", required = false) MultipartFile image, @Valid String id, @Valid String userid, @Valid String fileid) throws IOException { - if (image != null && !StringUtils.isBlank(fileid)) { + public ModelAndView messageimage(ModelMap map, + HttpServletRequest request, + @RequestParam(value = "image", required = false) MultipartFile image, + @Valid String id, + @Valid String userid, + @Valid String fileid) throws IOException { + logger.info("messageimage id {}, fileid {}", id, fileid); + if (image != null && StringUtils.isNotBlank(fileid)) { File tempFile = File.createTempFile(fileid, ".png"); try { - String fileName = "upload/" + fileid + "_cooperation"; - File imageFile = new File(path, fileName); + // 创建临时图片文件 if (!tempFile.getParentFile().exists()) { tempFile.getParentFile().mkdirs(); } + // 写入临时文件 FileCopyUtils.copy(image.getBytes(), tempFile); ChatMessage chatMessage = chatMessageRepository.findById(id); chatMessage.setCooperation(true); chatMessageRepository.save(chatMessage); + // 写入协作文件 + String fileName = "upload/" + fileid + "_cooperation"; + File imageFile = new File(path, fileName); MainUtils.scaleImage(imageFile, tempFile, 0.1F); + // 保存到数据库 + StreamingFile sf = streamingFileRepository.findOne(fileid); + if (sf != null) { + sf.setCooperation(jpaBlobHelper.createBlobWithFile(imageFile)); + streamingFileRepository.save(sf); + } OutMessageRouter router = null; AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(chatMessage.getUserid(), chatMessage.getOrgi()); @@ -818,7 +836,7 @@ public class AgentController extends Handler { router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel()); MessageOutContent outMessage = new MessageOutContent(); if (router != null) { - outMessage.setMessage("/res/image.html?id=" + fileName); + outMessage.setMessage("/res/image.html?id=" + fileid + "&cooperation=true"); outMessage.setFilename(imageFile.getName()); outMessage.setAttachmentid(chatMessage.getAttachmentid()); @@ -841,36 +859,33 @@ public class AgentController extends Handler { return request(super.createRequestPageTempletResponse("/public/success")); } - private String processAttachmentFile(MultipartFile file, HttpServletRequest request) throws IOException { + private String processAttachmentFile(final MultipartFile multipart, final String fileid, HttpServletRequest request) throws IOException { String id = null; - if (file.getSize() > 0) { //文件尺寸 限制 ?在 启动 配置中 设置 的最大值,其他地方不做限制 - String fileid = MainUtils.md5(file.getBytes()); //使用 文件的 MD5作为 ID,避免重复上传大文件 - if (StringUtils.isNotBlank(fileid)) { - AttachmentFile attachmentFile = new AttachmentFile(); - attachmentFile.setCreater(super.getUser(request).getId()); - attachmentFile.setOrgi(super.getOrgi(request)); - attachmentFile.setOrgan(super.getUser(request).getOrgan()); - attachmentFile.setModel(MainContext.ModelType.WEBIM.toString()); - attachmentFile.setFilelength((int) file.getSize()); - if (file.getContentType() != null && file.getContentType().length() > 255) { - attachmentFile.setFiletype(file.getContentType().substring(0, 255)); - } else { - attachmentFile.setFiletype(file.getContentType()); - } - File uploadFile = new File(file.getOriginalFilename()); - if (uploadFile.getName() != null && uploadFile.getName().length() > 255) { - attachmentFile.setTitle(uploadFile.getName().substring(0, 255)); - } else { - attachmentFile.setTitle(uploadFile.getName()); - } - if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) { - attachmentFile.setImage(true); - } - attachmentFile.setFileid(fileid); - attachementRes.save(attachmentFile); - FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes()); - id = attachmentFile.getId(); + if (multipart.getSize() > 0) { //文件尺寸 限制 ?在 启动 配置中 设置 的最大值,其他地方不做限制 + AttachmentFile attachmentFile = new AttachmentFile(); + attachmentFile.setCreater(super.getUser(request).getId()); + attachmentFile.setOrgi(super.getOrgi(request)); + attachmentFile.setOrgan(super.getUser(request).getOrgan()); + attachmentFile.setModel(MainContext.ModelType.WEBIM.toString()); + attachmentFile.setFilelength((int) multipart.getSize()); + if (multipart.getContentType() != null && multipart.getContentType().length() > 255) { + attachmentFile.setFiletype(multipart.getContentType().substring(0, 255)); + } else { + attachmentFile.setFiletype(multipart.getContentType()); } + File uploadFile = new File(multipart.getOriginalFilename()); + if (uploadFile.getName() != null && uploadFile.getName().length() > 255) { + attachmentFile.setTitle(uploadFile.getName().substring(0, 255)); + } else { + attachmentFile.setTitle(uploadFile.getName()); + } + if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) { + attachmentFile.setImage(true); + } + attachmentFile.setFileid(fileid); + attachementRes.save(attachmentFile); + FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), multipart.getBytes()); + id = attachmentFile.getId(); } return id; } @@ -879,7 +894,7 @@ public class AgentController extends Handler { @RequestMapping(value = "/contacts") @Menu(type = "apps", subtype = "contacts") public ModelAndView contacts(ModelMap map, HttpServletRequest request, @Valid String contactsid, @Valid String userid, @Valid String agentserviceid, @Valid String agentuserid) { - if (!StringUtils.isBlank(userid) && !StringUtils.isBlank(contactsid)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(contactsid)) { List onlineUserList = this.onlineUserRes.findByUseridAndOrgi(userid, super.getOrgi(request)); if (onlineUserList.size() > 0) { OnlineUser onlineUser = onlineUserList.get(0); @@ -925,9 +940,9 @@ public class AgentController extends Handler { @Valid String agentserviceid, @Valid String agentuserid, @Valid String channel) { - if (!StringUtils.isBlank(userid) && !StringUtils.isBlank(agentuserid)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { AgentUser agentUser = this.agentUserRepository.findByIdAndOrgi(agentuserid, super.getOrgi(request)); - if (agentUser != null && !StringUtils.isBlank(agentUser.getAgentserviceid())) { + if (agentUser != null && StringUtils.isNotBlank(agentUser.getAgentserviceid())) { List summaries = this.serviceSummaryRes.findByAgentserviceidAndOrgi(agentUser.getAgentserviceid(), super.getOrgi(request)); if (summaries.size() > 0) { map.addAttribute("summary", summaries.get(0)); @@ -955,7 +970,7 @@ public class AgentController extends Handler { @Valid String agentserviceid, @Valid String agentuserid, @Valid String channel) { - if (!StringUtils.isBlank(userid) && !StringUtils.isBlank(agentuserid)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { summary.setOrgi(super.getOrgi(request)); summary.setCreater(super.getUser(request).getId()); @@ -981,7 +996,7 @@ public class AgentController extends Handler { @RequestMapping(value = "/transfer") @Menu(type = "apps", subtype = "transfer") public ModelAndView transfer(ModelMap map, HttpServletRequest request, @Valid String userid, @Valid String agentserviceid, @Valid String agentuserid) { - if (!StringUtils.isBlank(userid) && !StringUtils.isBlank(agentuserid)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid)) { //map.addAttribute("organList", organRes.findByOrgiAndOrgid(super.getOrgi(request),super.getOrgid(request))) ; List skillList = OnlineUserUtils.organ(super.getOrgi(request), true); @@ -1022,7 +1037,7 @@ public class AgentController extends Handler { @RequestMapping(value = "/transfer/agent") @Menu(type = "apps", subtype = "transferagent") public ModelAndView transferagent(ModelMap map, HttpServletRequest request, @Valid String organ) { - if (!StringUtils.isBlank(organ)) { + if (StringUtils.isNotBlank(organ)) { List usersids = new ArrayList(); List agentStatusList = AutomaticServiceDist.getAgentStatus(organ, super.getOrgi(request)); if (!agentStatusList.isEmpty()) { @@ -1047,7 +1062,7 @@ public class AgentController extends Handler { @RequestMapping(value = "/transfer/save") @Menu(type = "apps", subtype = "transfersave") public ModelAndView transfersave(ModelMap map, HttpServletRequest request, @Valid String userid, @Valid String agentserviceid, @Valid String agentuserid, @Valid String agentno, @Valid String memo) { - if (!StringUtils.isBlank(userid) && !StringUtils.isBlank(agentuserid) && !StringUtils.isBlank(agentno)) { + if (StringUtils.isNotBlank(userid) && StringUtils.isNotBlank(agentuserid) && StringUtils.isNotBlank(agentno)) { AgentUser agentUser = (AgentUser) CacheHelper.getAgentUserCacheBean().getCacheObject(userid, super.getOrgi(request)); AgentService agentService = this.agentServiceRepository.findByIdAndOrgi(agentserviceid, super.getOrgi(request)); if (agentUser != null) { @@ -1081,7 +1096,7 @@ public class AgentController extends Handler { if (agentService != null) { agentService.setAgentno(agentno); - if (!StringUtils.isBlank(memo)) { + if (StringUtils.isNotBlank(memo)) { agentService.setTransmemo(memo); } agentService.setTrans(true); @@ -1103,7 +1118,7 @@ public class AgentController extends Handler { quickTypeList.addAll(priQuickTypeList); map.addAttribute("pubQuickTypeList", quickTypeList); - if (!StringUtils.isBlank(typeid)) { + if (StringUtils.isNotBlank(typeid)) { map.addAttribute("quickType", quickTypeRes.findByIdAndOrgi(typeid, super.getOrgi(request))); } @@ -1114,7 +1129,7 @@ public class AgentController extends Handler { @RequestMapping("/quickreply/add") @Menu(type = "setting", subtype = "quickreplyadd", admin = true) public ModelAndView quickreplyadd(ModelMap map, HttpServletRequest request, @Valid String parentid) { - if (!StringUtils.isBlank(parentid)) { + if (StringUtils.isNotBlank(parentid)) { map.addAttribute("quickType", quickTypeRes.findByIdAndOrgi(parentid, super.getOrgi(request))); } map.addAttribute("quickTypeList", quickTypeRes.findByOrgiAndQuicktypeAndCreater(super.getOrgi(request), MainContext.QuickTypeEnum.PRI.toString(), super.getUser(request).getId())); @@ -1124,7 +1139,7 @@ public class AgentController extends Handler { @RequestMapping("/quickreply/save") @Menu(type = "setting", subtype = "quickreply", admin = true) public ModelAndView quickreplysave(ModelMap map, HttpServletRequest request, @Valid QuickReply quickReply) { - if (!StringUtils.isBlank(quickReply.getTitle()) && !StringUtils.isBlank(quickReply.getContent())) { + if (StringUtils.isNotBlank(quickReply.getTitle()) && StringUtils.isNotBlank(quickReply.getContent())) { quickReply.setOrgi(super.getOrgi(request)); quickReply.setCreater(super.getUser(request).getId()); quickReply.setType(MainContext.QuickTypeEnum.PRI.toString()); @@ -1158,7 +1173,7 @@ public class AgentController extends Handler { @RequestMapping("/quickreply/update") @Menu(type = "setting", subtype = "quickreply", admin = true) public ModelAndView quickreplyupdate(ModelMap map, HttpServletRequest request, @Valid QuickReply quickReply) { - if (!StringUtils.isBlank(quickReply.getId())) { + if (StringUtils.isNotBlank(quickReply.getId())) { QuickReply temp = quickReplyRes.findOne(quickReply.getId()); quickReply.setOrgi(super.getOrgi(request)); quickReply.setCreater(super.getUser(request).getId()); @@ -1175,7 +1190,7 @@ public class AgentController extends Handler { @Menu(type = "apps", subtype = "kbs") public ModelAndView addtype(ModelMap map, HttpServletRequest request, @Valid String typeid) { map.addAttribute("quickTypeList", quickTypeRes.findByOrgiAndQuicktypeAndCreater(super.getOrgi(request), MainContext.QuickTypeEnum.PRI.toString(), super.getUser(request).getId())); - if (!StringUtils.isBlank(typeid)) { + if (StringUtils.isNotBlank(typeid)) { map.addAttribute("quickType", quickTypeRes.findByIdAndOrgi(typeid, super.getOrgi(request))); } return request(super.createRequestPageTempletResponse("/apps/agent/quickreply/addtype")); diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/internet/IMController.java b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/internet/IMController.java index 43137770..ea22db1e 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/internet/IMController.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/apps/internet/IMController.java @@ -24,6 +24,7 @@ import com.chatopera.cc.app.cache.CacheHelper; import com.chatopera.cc.app.handler.Handler; import com.chatopera.cc.app.im.util.RichMediaUtils; import com.chatopera.cc.app.model.*; +import com.chatopera.cc.app.persistence.blob.JpaBlobHelper; import com.chatopera.cc.app.persistence.es.ContactsRepository; import com.chatopera.cc.app.persistence.repository.*; import com.chatopera.cc.util.*; @@ -78,6 +79,12 @@ public class IMController extends Handler { @Value("${web.upload-path}") private String path; + @Autowired + private StreamingFileRepository streamingFileRepository; + + @Autowired + private JpaBlobHelper jpaBlobHelper; + @Autowired private ConsultInviteRepository inviteRepository; @@ -707,62 +714,76 @@ public class IMController extends Handler { @RequestMapping("/image/upload") @Menu(type = "im", subtype = "image", access = true) - public ModelAndView upload(ModelMap map, HttpServletRequest request, @RequestParam(value = "imgFile", required = false) MultipartFile imgFile, @Valid String channel, @Valid String userid, @Valid String username, @Valid String appid, @Valid String orgi, @Valid String paste) throws IOException { + public ModelAndView upload(ModelMap map, HttpServletRequest request, + @RequestParam(value = "imgFile", required = false) MultipartFile multipart, + @Valid String channel, + @Valid String userid, + @Valid String username, + @Valid String appid, + @Valid String orgi, + @Valid String paste) throws IOException { ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/upload")); UploadStatus upload = null; String fileName = null; - if (imgFile != null - && imgFile.getOriginalFilename().lastIndexOf(".") > 0 + if (multipart != null + && multipart.getOriginalFilename().lastIndexOf(".") > 0 && StringUtils.isNotBlank(userid)) { File uploadDir = new File(path, "upload"); if (!uploadDir.exists()) { uploadDir.mkdirs(); } - String fileid = MainUtils.md5(imgFile.getBytes()); - if (imgFile.getContentType() != null - && imgFile.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) { + + String fileid = MainUtils.getUUID(); + StreamingFile sf = new StreamingFile(); + sf.setId(fileid); + sf.setName(multipart.getOriginalFilename()); + sf.setMime(multipart.getContentType()); + if (multipart.getContentType() != null + && multipart.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) { // 检查文件格式 - String invalid = AttachementFormatValidator.getInstance().validate(Constants.ATTACHMENT_TYPE_IMAGE, imgFile.getOriginalFilename()); + String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_IMAGE, multipart.getOriginalFilename()); if (invalid == null) { fileName = "upload/" + fileid + "_original"; File imageFile = new File(path, fileName); - FileCopyUtils.copy(imgFile.getBytes(), imageFile); + FileCopyUtils.copy(multipart.getBytes(), imageFile); String thumbnailsFileName = "upload/" + fileid; - MainUtils.processImage(new File(path, thumbnailsFileName), imageFile); + File thumbnail = new File(path, thumbnailsFileName); + MainUtils.processImage(thumbnail, imageFile); + + // 存储数据库 + sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize())); + sf.setThumbnail(jpaBlobHelper.createBlobWithFile(thumbnail)); + streamingFileRepository.save(sf); + String fileUrl = "/res/image.html?id=" + fileid; + upload = new UploadStatus("0", fileUrl); - upload = new UploadStatus("0", "/res/image.html?id=" + thumbnailsFileName); - String image = "/res/image.html?id=" + thumbnailsFileName; - if (request.getServerPort() == 80) { - image = "/res/image.html?id=" + thumbnailsFileName; - } else { - image = "/res/image.html?id=" + thumbnailsFileName; - } if (paste == null) { if (StringUtils.isNotBlank(channel)) { - RichMediaUtils.uploadImageWithChannel(image, fileid, (int) imgFile.getSize(), imgFile.getName(), channel, userid, username, appid, orgi); + RichMediaUtils.uploadImageWithChannel(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), channel, userid, username, appid, orgi); } else { - RichMediaUtils.uploadImage(image, fileid, (int) imgFile.getSize(), imgFile.getName(), userid); + RichMediaUtils.uploadImage(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), userid); } } } else { upload = new UploadStatus(invalid); } } else { - String invalid = AttachementFormatValidator.getInstance().validate(Constants.ATTACHMENT_TYPE_FILE, imgFile.getOriginalFilename()); + String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_FILE, multipart.getOriginalFilename()); if (invalid == null) { - String id = processAttachmentFile(imgFile, request); + // 存储数据库 + sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize())); + streamingFileRepository.save(sf); + + // 存储到本地硬盘 + String id = processAttachmentFile(multipart, fileid, request); upload = new UploadStatus("0", "/res/file.html?id=" + id); String file = "/res/file.html?id=" + id; - if (request.getServerPort() == 80) { - file = "/res/file.html?id=" + id; - } else { - file = "/res/file.html?id=" + id; - } - File tempFile = new File(imgFile.getOriginalFilename()); + + File tempFile = new File(multipart.getOriginalFilename()); if (StringUtils.isNotBlank(channel)) { - RichMediaUtils.uploadFileWithChannel(file, (int) imgFile.getSize(), tempFile.getName(), channel, userid, username, appid, orgi, id); + RichMediaUtils.uploadFileWithChannel(file, (int) multipart.getSize(), tempFile.getName(), channel, userid, username, appid, orgi, id); } else { - RichMediaUtils.uploadFile(file, (int) imgFile.getSize(), tempFile.getName(), userid, id); + RichMediaUtils.uploadFile(file, (int) multipart.getSize(), tempFile.getName(), userid, id); } } else { upload = new UploadStatus(invalid); @@ -775,36 +796,33 @@ public class IMController extends Handler { return view; } - private String processAttachmentFile(MultipartFile file, HttpServletRequest request) throws IOException { + private String processAttachmentFile(final MultipartFile file, final String fileid, HttpServletRequest request) throws IOException { String id = null; if (file.getSize() > 0) { //文件尺寸 限制 ?在 启动 配置中 设置 的最大值,其他地方不做限制 - String fileid = MainUtils.md5(file.getBytes()); //使用 文件的 MD5作为 ID,避免重复上传大文件 - if (StringUtils.isNotBlank(fileid)) { - AttachmentFile attachmentFile = new AttachmentFile(); - attachmentFile.setCreater(super.getUser(request).getId()); - attachmentFile.setOrgi(super.getOrgi(request)); - attachmentFile.setOrgan(super.getUser(request).getOrgan()); - attachmentFile.setModel(MainContext.ModelType.WEBIM.toString()); - attachmentFile.setFilelength((int) file.getSize()); - if (file.getContentType() != null && file.getContentType().length() > 255) { - attachmentFile.setFiletype(file.getContentType().substring(0, 255)); - } else { - attachmentFile.setFiletype(file.getContentType()); - } - File uploadFile = new File(file.getOriginalFilename()); - if (uploadFile.getName() != null && uploadFile.getName().length() > 255) { - attachmentFile.setTitle(uploadFile.getName().substring(0, 255)); - } else { - attachmentFile.setTitle(uploadFile.getName()); - } - if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) { - attachmentFile.setImage(true); - } - attachmentFile.setFileid(fileid); - attachementRes.save(attachmentFile); - FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes()); - id = attachmentFile.getId(); + AttachmentFile attachmentFile = new AttachmentFile(); + attachmentFile.setCreater(super.getUser(request).getId()); + attachmentFile.setOrgi(super.getOrgi(request)); + attachmentFile.setOrgan(super.getUser(request).getOrgan()); + attachmentFile.setModel(MainContext.ModelType.WEBIM.toString()); + attachmentFile.setFilelength((int) file.getSize()); + if (file.getContentType() != null && file.getContentType().length() > 255) { + attachmentFile.setFiletype(file.getContentType().substring(0, 255)); + } else { + attachmentFile.setFiletype(file.getContentType()); } + File uploadFile = new File(file.getOriginalFilename()); + if (uploadFile.getName() != null && uploadFile.getName().length() > 255) { + attachmentFile.setTitle(uploadFile.getName().substring(0, 255)); + } else { + attachmentFile.setTitle(uploadFile.getName()); + } + if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) { + attachmentFile.setImage(true); + } + attachmentFile.setFileid(fileid); + attachementRes.save(attachmentFile); + FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes()); + id = attachmentFile.getId(); } return id; } diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/resource/MediaController.java b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/resource/MediaController.java index 020f5802..b08c2de2 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/app/handler/resource/MediaController.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/handler/resource/MediaController.java @@ -16,42 +16,53 @@ */ package com.chatopera.cc.app.handler.resource; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URL; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.validation.Valid; - +import com.chatopera.cc.app.basic.MainUtils; +import com.chatopera.cc.app.handler.Handler; +import com.chatopera.cc.app.model.AttachmentFile; +import com.chatopera.cc.app.model.StreamingFile; +import com.chatopera.cc.app.model.UploadStatus; +import com.chatopera.cc.app.persistence.blob.JpaBlobHelper; +import com.chatopera.cc.app.persistence.repository.AttachmentRepository; +import com.chatopera.cc.app.persistence.repository.StreamingFileRepository; +import com.chatopera.cc.util.Menu; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.tomcat.util.http.fileupload.IOUtils; +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.stereotype.Controller; import org.springframework.ui.ModelMap; -import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.ModelAndView; -import com.chatopera.cc.util.Menu; -import com.chatopera.cc.app.basic.MainUtils; -import com.chatopera.cc.app.persistence.repository.AttachmentRepository; -import com.chatopera.cc.app.handler.Handler; -import com.chatopera.cc.app.model.AttachmentFile; -import com.chatopera.cc.app.model.UploadStatus; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.sql.SQLException; @Controller @RequestMapping("/res") public class MediaController extends Handler { + private final static Logger logger = LoggerFactory.getLogger(MediaController.class); @Value("${web.upload-path}") private String path; + @Autowired + private StreamingFileRepository streamingFileRepository; + + @Autowired + private JpaBlobHelper jpaBlobHelper; + private String TEMPLATE_DATA_PATH = "WEB-INF/data/templates/"; @Autowired @@ -59,32 +70,25 @@ public class MediaController extends Handler { @RequestMapping("/image") @Menu(type = "resouce", subtype = "image", access = true) - public void index(HttpServletResponse response, @Valid String id) throws IOException { - File file = new File(path, id); - if (!StringUtils.isBlank(id) && !(id.endsWith(".png") || id.endsWith(".jpg"))) { - if (id.endsWith("_original") && !file.exists()) { - File orgFile = new File(path, id.substring(0, id.indexOf("_original"))); - if (orgFile.exists()) { - MainUtils.processImage(file = new File(path, id), orgFile); - } - } else if (!StringUtils.isBlank(id) && file.exists() && !id.endsWith("_original")) { - File originalFile = new File(path, id + "_original"); - if (!originalFile.exists()) { - MainUtils.processImage(new File(path, id + "_original"), file); - } - } else if (!StringUtils.isBlank(id) && !file.exists() && !id.endsWith("_original")) { - File destFile = new File(path, id + "_original"); - if (destFile.exists()) { - MainUtils.processImage(new File(path + id), destFile); - } - file = new File(path, id); + public void index(HttpServletResponse response, + @Valid String id, + @RequestParam(value = "original", required = false) boolean original, + @RequestParam(value = "cooperation", required = false) boolean cooperation) throws IOException, SQLException { + logger.info("index id {}, original {}, cooperation {}", id, original, cooperation); + StreamingFile sf = streamingFileRepository.findOne(id); + if (sf != null) { + response.setHeader("Content-Type", sf.getMime()); + response.setContentType(sf.getMime()); + if (cooperation && (sf.getCooperation() != null)) { // 协作文件 + IOUtils.copy(sf.getCooperation().getBinaryStream(), response.getOutputStream()); + } else if (original && sf.getData() != null) { // 源文件 + IOUtils.copy(sf.getData().getBinaryStream(), response.getOutputStream()); + } else if (sf.getThumbnail() != null) { // 缩略图 + IOUtils.copy(sf.getThumbnail().getBinaryStream(), response.getOutputStream()); + } else { + logger.warn("[index] can not get streaming file id {}, original {}, cooperation {}", id, original, cooperation); } } - if (file.exists() && file.isFile()) { - response.setHeader("Content-Type", "image/png"); - response.setContentType("image/png"); - response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path, id))); - } } @RequestMapping("/voice") @@ -102,7 +106,7 @@ public class MediaController extends Handler { byte[] data = new byte[1024]; int length = 0; OutputStream out = response.getOutputStream(); - if (!StringUtils.isBlank(url)) { + if (StringUtils.isNotBlank(url)) { InputStream input = new URL(url).openStream(); while ((length = input.read(data)) > 0) { out.write(data, 0, length); @@ -113,44 +117,43 @@ public class MediaController extends Handler { @RequestMapping("/image/upload") @Menu(type = "resouce", subtype = "imageupload", access = false) - public ModelAndView upload(ModelMap map, HttpServletRequest request, @RequestParam(value = "imgFile", required = false) MultipartFile imgFile) throws IOException { + public ModelAndView upload(ModelMap map, + HttpServletRequest request, + @RequestParam(value = "imgFile", required = false) MultipartFile multipart) throws IOException { ModelAndView view = request(super.createRequestPageTempletResponse("/public/upload")); - UploadStatus upload = null; - String fileName = null; - if (imgFile != null && imgFile.getOriginalFilename().lastIndexOf(".") > 0) { + UploadStatus notify = null; + if (multipart != null && multipart.getOriginalFilename().lastIndexOf(".") > 0) { File uploadDir = new File(path, "upload"); if (!uploadDir.exists()) { uploadDir.mkdirs(); } - fileName = "upload/" + MainUtils.md5(imgFile.getBytes()) + imgFile.getOriginalFilename().substring(imgFile.getOriginalFilename().lastIndexOf(".")).toLowerCase(); - FileCopyUtils.copy(imgFile.getBytes(), new File(path, fileName)); - - String fileURL = request.getScheme() + "://" + request.getServerName() + "/res/image.html?id=" + fileName; - if (request.getServerPort() == 80) { - fileURL = request.getScheme() + "://" + request.getServerName() + "/res/image.html?id=" + fileName; - } else { - fileURL = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/res/image.html?id=" + fileName; - } - upload = new UploadStatus("0", fileURL); //图片直接发送给 客户,不用返回 + String fileid = MainUtils.getUUID(); + StreamingFile sf = new StreamingFile(); + sf.setId(fileid); + sf.setName(multipart.getOriginalFilename()); + sf.setMime(multipart.getContentType()); + sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize())); + streamingFileRepository.save(sf); + String fileURL = "/res/image.html?id=" + fileid; + notify = new UploadStatus("0", fileURL); //图片直接发送给 客户,不用返回 } else { - upload = new UploadStatus("请选择图片文件"); + notify = new UploadStatus("请选择图片文件"); } - map.addAttribute("upload", upload); + map.addAttribute("upload", notify); return view; } @RequestMapping("/file") @Menu(type = "resouce", subtype = "file", access = false) - public void file(HttpServletResponse response, HttpServletRequest request, @Valid String id) throws IOException { - if (!StringUtils.isBlank(id)) { + public void file(HttpServletResponse response, HttpServletRequest request, @Valid String id) throws IOException, SQLException { + if (StringUtils.isNotBlank(id)) { AttachmentFile attachmentFile = attachementRes.findByIdAndOrgi(id, super.getOrgi(request)); - if (attachmentFile != null) { - response.setContentType(attachmentFile.getFiletype()); - response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(attachmentFile.getTitle(), "UTF-8")); - if (StringUtils.isNotBlank(attachmentFile.getModel()) && attachmentFile.getModel().equals("app")) { - response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path, "app/" + attachmentFile.getFileid()))); - } else { - response.getOutputStream().write(FileUtils.readFileToByteArray(new File(path, "upload/" + attachmentFile.getFileid()))); + if (attachmentFile != null && attachmentFile.getFileid() != null) { + StreamingFile sf = streamingFileRepository.findOne(attachmentFile.getFileid()); + if (sf != null) { + response.setContentType(attachmentFile.getFiletype()); + response.setHeader("Content-Disposition", "attachment;filename=" + java.net.URLEncoder.encode(attachmentFile.getTitle(), "UTF-8")); + IOUtils.copy(sf.getData().getBinaryStream(), response.getOutputStream()); } } } @@ -159,7 +162,7 @@ public class MediaController extends Handler { @RequestMapping("/template") @Menu(type = "resouce", subtype = "template", access = false) public void template(HttpServletResponse response, HttpServletRequest request, @Valid String filename) throws IOException { - if (!StringUtils.isBlank(filename)) { + if (StringUtils.isNotBlank(filename)) { InputStream is = MediaController.class.getClassLoader().getResourceAsStream(TEMPLATE_DATA_PATH + filename); if (is != null) { response.setContentType("text/plain"); diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/model/StreamingFile.java b/contact-center/app/src/main/java/com/chatopera/cc/app/model/StreamingFile.java new file mode 100644 index 00000000..2d2cc041 --- /dev/null +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/model/StreamingFile.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2018 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.chatopera.cc.app.model; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Proxy; + +import java.sql.Blob; +import javax.persistence.*; +import javax.validation.constraints.NotNull; + +@Entity +@Table(name = "cs_stream_file") +@Proxy(lazy = false) +public class StreamingFile implements java.io.Serializable { + + private String id; + + @NotNull + private String name; + + private String mime; // Media Type over HTTP + + @NotNull + private Blob data; + + private Blob thumbnail; // 图片缩略图 + + private Blob cooperation; // 图片协作图 + + @Id + @Column(length = 32) + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "assigned") + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + @NotNull + public String getName() { + return name; + } + + public void setName(@NotNull String name) { + this.name = name; + } + + @NotNull + public Blob getData() { + return data; + } + + public void setData(@NotNull Blob data) { + this.data = data; + } + + public Blob getThumbnail() { + return thumbnail; + } + + public void setThumbnail(Blob thumbnail) { + this.thumbnail = thumbnail; + } + + public String getMime() { + return mime; + } + + public void setMime(String mime) { + this.mime = mime; + } + + public Blob getCooperation() { + return cooperation; + } + + public void setCooperation(Blob cooperation) { + this.cooperation = cooperation; + } +} diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/blob/JpaBlobHelper.java b/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/blob/JpaBlobHelper.java new file mode 100644 index 00000000..36b23d17 --- /dev/null +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/blob/JpaBlobHelper.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.chatopera.cc.app.persistence.blob; + +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.EnableTransactionManagement; +import org.springframework.transaction.annotation.Transactional; + +import javax.persistence.EntityManagerFactory; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.sql.Blob; + +@Component +@Transactional +public class JpaBlobHelper { + + private final SessionFactory sessionFactory; + + @Autowired + public JpaBlobHelper(EntityManagerFactory factory) { + if (factory.unwrap(SessionFactory.class) == null) { + throw new NullPointerException("factory is not a hibernate factory"); + } + this.sessionFactory = factory.unwrap(SessionFactory.class); + } + + + public Blob createBlob(InputStream content, long size) { + return sessionFactory.getCurrentSession().getLobHelper().createBlob(content, size); + } + + public Blob createBlobWithFile(final File file) throws FileNotFoundException { + return createBlob(new FileInputStream(file), file.length()); + } + +} diff --git a/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/repository/StreamingFileRepository.java b/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/repository/StreamingFileRepository.java new file mode 100644 index 00000000..78fe576c --- /dev/null +++ b/contact-center/app/src/main/java/com/chatopera/cc/app/persistence/repository/StreamingFileRepository.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2018 Chatopera Inc, + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.chatopera.cc.app.persistence.repository; + +import com.chatopera.cc.app.model.StreamingFile; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface StreamingFileRepository extends JpaRepository { +} diff --git a/contact-center/app/src/main/java/com/chatopera/cc/util/AttachementFormatValidator.java b/contact-center/app/src/main/java/com/chatopera/cc/util/StreamingFileUtils.java similarity index 87% rename from contact-center/app/src/main/java/com/chatopera/cc/util/AttachementFormatValidator.java rename to contact-center/app/src/main/java/com/chatopera/cc/util/StreamingFileUtils.java index df5cd4a5..35a9ae99 100644 --- a/contact-center/app/src/main/java/com/chatopera/cc/util/AttachementFormatValidator.java +++ b/contact-center/app/src/main/java/com/chatopera/cc/util/StreamingFileUtils.java @@ -19,20 +19,20 @@ package com.chatopera.cc.util; import java.util.Arrays; import java.util.HashMap; -public class AttachementFormatValidator { +public class StreamingFileUtils { - private static AttachementFormatValidator singleton = new AttachementFormatValidator(); + private static StreamingFileUtils singleton = new StreamingFileUtils(); private final HashMap extMap = new HashMap(); - private AttachementFormatValidator() { + private StreamingFileUtils() { extMap.put(Constants.ATTACHMENT_TYPE_IMAGE, "gif,jpg,jpeg,png,bmp"); extMap.put(Constants.ATTACHMENT_TYPE_FILE, "doc,docx,xls,xlsx,ppt,htm,html,txt,zip,rar,gz,bz2,c66"); extMap.put("flash", "swf,flv"); extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb"); } - public static AttachementFormatValidator getInstance() { + public static StreamingFileUtils getInstance() { return singleton; } @@ -49,4 +49,5 @@ public class AttachementFormatValidator { } return null; } + } diff --git a/contact-center/app/src/main/resources/application.properties b/contact-center/app/src/main/resources/application.properties index 248feb69..092f7646 100644 --- a/contact-center/app/src/main/resources/application.properties +++ b/contact-center/app/src/main/resources/application.properties @@ -31,11 +31,6 @@ server.log.path=../logs server.log.level=INFO web.upload-path=../data -# multi part -spring.servlet.multipart.enabled=true -spring.servlet.multipart.max-file-size=20MB -spring.servlet.multipart.max-request-size=50MB - # IM Server uk.im.server.port=8036 uk.im.server.host=localhost @@ -153,4 +148,12 @@ cskefu.callout.watch.interval=60000 ############################################## storage.minio.url=http://192.168.2.217:9000 storage.minio.access_key=M19Q8YJ8FzLyQtST7r0 -storage.minio.secret_key=KHv6qjddHD4HfR1m7fjY7HglSO1WOSzIeTERRUUc \ No newline at end of file +storage.minio.secret_key=KHv6qjddHD4HfR1m7fjY7HglSO1WOSzIeTERRUUc + +# multi part +spring.servlet.multipart.enabled=true +spring.servlet.multipart.max-file-size=15MB +spring.servlet.multipart.max-request-size=15MB + +# MySQL Blob +spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext diff --git a/contact-center/app/src/main/resources/templates/apps/agent/media/messageimage.html b/contact-center/app/src/main/resources/templates/apps/agent/media/messageimage.html index 78506c11..d93225d4 100644 --- a/contact-center/app/src/main/resources/templates/apps/agent/media/messageimage.html +++ b/contact-center/app/src/main/resources/templates/apps/agent/media/messageimage.html @@ -35,7 +35,7 @@ //创建新的图片对象 var img = new Image(); //指定图片的URL - img.src = "/res/image.html?id=upload/${chatMessage.attachmentid!''}_cooperation"; + img.src = "/res/image.html?id=${chatMessage.attachmentid!''}&cooperation=true&original=true"; //浏览器加载图片完毕后再绘制图片 img.onload = function(){ //以Canvas画布上的坐标(10,10)为起始点,绘制图像 @@ -49,7 +49,7 @@
- +
你的浏览器不支持 canvas 绘图 diff --git a/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.html b/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.html index bf8a0786..75952ee4 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.html +++ b/contact-center/app/src/main/resources/templates/apps/im/chatbot/index.html @@ -493,7 +493,7 @@ var chat=document.getElementsByClassName('chatting-left').innerText; chat = data.message; if(data.messageType == "image"){ - chat = "" ; + chat = "" ; }else if(data.messageType == "file"){ chat = "" ; } diff --git a/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.html b/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.html index 0a759547..2fcb6b5f 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.html +++ b/contact-center/app/src/main/resources/templates/apps/im/chatbot/mobile.html @@ -302,7 +302,7 @@ var chat=document.getElementsByClassName('chatting-left').innerText; chat = data.message; if(data.messageType == "image"){ - chat = "" ; + chat = "" ; }else if(data.messageType == "cooperation"){ chat = "您收到一个协作邀请,点击进入协作" ; }else if(data.messageType == "action"){ @@ -324,7 +324,7 @@ } function acceptInvite(msgid,fileid){ document.getElementById("cooperation").style.display = "block" ; - document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=upload/"+fileid ; + document.getElementById("ukefu_img_ctx").src = "/res/image.html?id="+fileid + "&cooperation=true&original=true"; $("#ukefu_img_ctx").load(function() { var height = document.getElementById("ukefu-image-content").offsetHeight; @@ -348,7 +348,7 @@ //创建新的图片对象 var img = new Image(); //指定图片的URL - img.src = "/res/image.html?id=upload/" + fileid + "_cooperation"; + img.src = "/res/image.html?id=" + fileid + "&cooperation=true&original=true"; //浏览器加载图片完毕后再绘制图片 img.onload = function() { ctx.clearRect(0,0,canvas.width,canvas.height); diff --git a/contact-center/app/src/main/resources/templates/apps/im/index.html b/contact-center/app/src/main/resources/templates/apps/im/index.html index cd1b0b11..ec5f2e52 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/index.html +++ b/contact-center/app/src/main/resources/templates/apps/im/index.html @@ -491,7 +491,7 @@ var chat=document.getElementsByClassName('chatting-left').innerText; chat = data.message; if(data.messageType == "image"){ - chat = "" ; + chat = "" ; }else if(data.messageType == "file"){ chat = "" ; } diff --git a/contact-center/app/src/main/resources/templates/apps/im/media/message.html b/contact-center/app/src/main/resources/templates/apps/im/media/message.html index 259fece2..688d62cc 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/media/message.html +++ b/contact-center/app/src/main/resources/templates/apps/im/media/message.html @@ -1,5 +1,5 @@ <#if chatMessage.msgtype?? && chatMessage.msgtype == "image"> - + <#elseif chatMessage.msgtype?? && chatMessage.msgtype == "cooperation"> 您收到一个协作邀请,点击进入协作 <#elseif chatMessage.msgtype?? && chatMessage.msgtype == "file"> diff --git a/contact-center/app/src/main/resources/templates/apps/im/mobile.html b/contact-center/app/src/main/resources/templates/apps/im/mobile.html index 12efd967..e0496030 100644 --- a/contact-center/app/src/main/resources/templates/apps/im/mobile.html +++ b/contact-center/app/src/main/resources/templates/apps/im/mobile.html @@ -300,7 +300,7 @@ var chat=document.getElementsByClassName('chatting-left').innerText; chat = data.message; if(data.messageType == "image"){ - chat = "" ; + chat = "" ; }else if(data.messageType == "cooperation"){ chat = "您收到一个协作邀请,点击进入协作" ; }else if(data.messageType == "action"){ @@ -322,7 +322,7 @@ } function acceptInvite(msgid,fileid){ document.getElementById("cooperation").style.display = "block" ; - document.getElementById("ukefu_img_ctx").src = "/res/image.html?id=upload/"+fileid ; + document.getElementById("ukefu_img_ctx").src = "/res/image.html?id="+fileid + "&cooperation=true&original=true"; $("#ukefu_img_ctx").load(function() { var height = document.getElementById("ukefu-image-content").offsetHeight; @@ -346,7 +346,7 @@ //创建新的图片对象 var img = new Image(); //指定图片的URL - img.src = "/res/image.html?id=upload/" + fileid + "_cooperation"; + img.src = "/res/image.html?id=" + fileid + "&cooperation=true&original=true"; //浏览器加载图片完毕后再绘制图片 img.onload = function() { ctx.clearRect(0,0,canvas.width,canvas.height);