Browse Source

支持发送文件

master
xie.bx 3 years ago
parent
commit
b9062a4680
  1. 12
      commom/src/main/java/com/lx/common/contant/Contant.java
  2. 11
      im-platform/src/main/java/com/lx/implatform/controller/FileController.java
  3. 20
      im-platform/src/main/java/com/lx/implatform/service/thirdparty/FileService.java
  4. 6
      im-ui/src/api/httpRequest.js
  5. 76
      im-ui/src/components/chat/MessageItem.vue
  6. 27
      im-ui/src/components/common/FileUpload.vue
  7. 4
      im-ui/src/main.js
  8. 3
      im-ui/src/store/chatStore.js
  9. 75
      im-ui/src/view/Chat.vue

12
commom/src/main/java/com/lx/common/contant/Contant.java

@ -0,0 +1,12 @@
package com.lx.common.contant;
public class Contant {
public static final long MAX_IMAGE_SIZE = 5*1024*1024;
public static final long MAX_FILE_SIZE = 10*1024*1024;
}

11
im-platform/src/main/java/com/lx/implatform/controller/FileController.java

@ -8,7 +8,6 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@ -27,12 +26,16 @@ public class FileController {
@Autowired
private FileService fileService;
@ApiOperation(value = "上传图片",notes="上传图片")
@ApiOperation(value = "上传图片",notes="上传图片,上传后返回原图和缩略图的url")
@PostMapping("/image/upload")
public Result<UploadImageVO> upload(MultipartFile file) {
public Result<UploadImageVO> uploadImage(MultipartFile file) {
return ResultUtils.success(fileService.uploadImage(file));
}
@ApiOperation(value = "上传文件",notes="上传文件,上传后返回文件url")
@PostMapping("/file/upload")
public Result<String> uploadFile(MultipartFile file) {
return ResultUtils.success(fileService.uploadFile(file),"");
}
}

20
im-platform/src/main/java/com/lx/implatform/service/thirdparty/FileService.java

@ -1,8 +1,8 @@
package com.lx.implatform.service.thirdparty;
import com.lx.common.contant.Contant;
import com.lx.common.enums.FileTypeEnum;
import com.lx.common.enums.ResultCode;
import com.lx.implatform.util.FileUtil;
import com.lx.implatform.exception.GlobalException;
import com.lx.implatform.util.FileUtil;
import com.lx.implatform.util.ImageUtil;
@ -48,8 +48,26 @@ public class FileService {
}
}
public String uploadFile(MultipartFile file){
// 大小校验
if(file.getSize() > Contant.MAX_FILE_SIZE){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"文件大小不能超过10M");
}
// 上传
String fileName = minioUtil.upload(bucketName,filePath,file);
if(StringUtils.isEmpty(fileName)){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"文件上传失败");
}
return generUrl(FileTypeEnum.FILE,fileName);
}
public UploadImageVO uploadImage(MultipartFile file){
try {
// 大小校验
if(file.getSize() > Contant.MAX_IMAGE_SIZE){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"图片大小不能超过5M");
}
// 图片格式校验
if(!FileUtil.isImage(file.getOriginalFilename())){
throw new GlobalException(ResultCode.PROGRAM_ERROR,"图片格式不合法");

6
im-ui/src/api/httpRequest.js

@ -1,10 +1,6 @@
import axios from 'axios'
import router from '@/router'
import qs from 'qs'
import merge from 'lodash/merge'
import {
Message
} from 'element-ui'
import {Message} from 'element-ui'
const http = axios.create({
timeout: 1000 * 30,

76
im-ui/src/components/chat/MessageItem.vue

@ -18,6 +18,19 @@
</div>
<span title="发送失败" v-show="loadFail" @click="handleSendFail" class="send-fail el-icon-warning"></span>
</div>
<div class="im-msg-file" v-if="msgInfo.type==2">
<div class="im-file-box">
<div class="im-file-info">
<el-link class="im-file-name" underline="true" target="_blank" type="primary" :href="data.url">{{data.name}}</el-link>
<div class="im-file-size">{{fileSize}}</div>
</div>
<div class="im-file-icon">
<span type="primary" class="el-icon-document"></span>
</div>
</div>
</div>
</div>
</div>
</div>
@ -58,11 +71,27 @@
},
computed:{
loading(){
return this.msgInfo.loadStatus && this.msgInfo.loadStatus === "loadding";
return this.msgInfo.loadStatus && this.msgInfo.loadStatus === "loading";
},
loadFail(){
return this.msgInfo.loadStatus && this.msgInfo.loadStatus === "fail";
}
},
data(){
return JSON.parse(this.msgInfo.content)
},
fileSize(){
let size = this.data.size;
if (size > 1024 * 1024) {
return Math.round(size / 1024 / 1024) + "M";
}
if (size > 1024) {
return Math.round(size / 1024) + "KB";
}
return size + "B";
},
},
mounted() {
//console.log(this.msgInfo);
}
}
</script>
@ -132,8 +161,6 @@
flex-wrap: nowrap;
flex-direction: row;
align-items: center;
.send-image{
min-width: 300px;
min-height: 200px;
@ -150,6 +177,43 @@
margin: 0 20px;
}
}
.im-msg-file{
display: flex;
flex-wrap: nowrap;
flex-direction: row;
align-items: center;
cursor: pointer;
.im-file-box{
display: flex;
flex-wrap: nowrap;
align-items: center;
width: 20%;
min-height: 80px;
border: #dddddd solid 1px;
border-radius: 3px;
background-color: #eeeeee;
padding: 10px 15px;
.im-file-info{
flex:1;
height: 100%;
text-align: left;
font-size: 14px;
.im-file-name {
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
}
}
.im-file-icon{
font-size: 50px;
color: #d42e07;
}
}
}
}
}
@ -196,6 +260,10 @@
.im-msg-image {
flex-direction: row-reverse;
}
.im-msg-file {
flex-direction: row-reverse;
}
}
}

27
im-ui/src/components/common/FileUpload.vue

@ -1,5 +1,8 @@
<template>
<el-upload :action="action" :accept="fileTypes.join(',')" :show-file-list="false" :on-success="handleSuccess"
<el-upload :action="action"
:accept="fileTypes==null?'':fileTypes.join(',')"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<slot></slot>
</el-upload>
@ -43,20 +46,20 @@
},
beforeUpload(file) {
//
let fileType = file.type;
let t = this.fileTypes.find((t) => t.toLowerCase() === fileType);
console.log(t);
if (t === undefined) {
this.$message.error(`文件格式错误,请上传以下格式的文件:${this.fileTypes.join("、")}`);
return false;
if(this.fileTypes && this.fileTypes.length > 0){
let fileType = file.type;
let t = this.fileTypes.find((t) => t.toLowerCase() === fileType);
if (t === undefined) {
this.$message.error(`文件格式错误,请上传以下格式的文件:${this.fileTypes.join("、")}`);
return false;
}
}
//
let size = file.size;
if (size > this.maxSize) {
if (this.maxSize && file.size > this.maxSize) {
this.$message.error(`文件大小不能超过 ${this.fileSizeStr}!`);
return false;
}
//
if (this.showLoading) {
this.loading = this.$loading({
lock: true,
@ -72,10 +75,10 @@
computed: {
fileSizeStr() {
if (this.maxSize > 1024 * 1024) {
return (this.maxSize / 1024 / 1024) + "M";
return Math.round(this.maxSize / 1024 / 1024) + "M";
}
if (this.maxSize > 1024) {
return (this.maxSize / 1024) + "KB";
return Math.round(this.maxSize / 1024) + "KB";
}
return this.maxSize + "B";
}

4
im-ui/src/main.js

@ -1,12 +1,10 @@
import Vue from 'vue'
import App from './App'
import router from './router'
import axios from 'axios'
import VueAxios from 'vue-axios'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import httpRequest from './api/httpRequest';
import * as socketApi from './api/wssocket' ;
import * as socketApi from './api/wssocket';
import store from './store';

3
im-ui/src/store/chatStore.js

@ -1,6 +1,3 @@
import httpRequest from '../api/httpRequest.js'
export default {
state: {

75
im-ui/src/view/Chat.vue

@ -37,13 +37,21 @@
<file-upload action="/api/image/upload"
:maxSize="5*1024*1024"
:fileTypes="['image/jpeg', 'image/png', 'image/jpg', 'image/gif']"
@before="beforeImageUpload"
@before="handleImageBefore"
@success="handleImageSuccess"
@fail="handleImageFail" >
<i class="el-icon-picture-outline"></i>
</file-upload>
</div>
<div class="el-icon-wallet"></div>
<div>
<file-upload action="/api/file/upload"
:maxSize="10*1024*1024"
@before="handleFileBefore"
@success="handleFileSuccess"
@fail="handleFileFail" >
<i class="el-icon-wallet"></i>
</file-upload>
</div>
<div class="el-icon-chat-dot-round"></div>
</div>
<textarea v-model="messageContent" ref="sendBox" class="send-text-area" @keyup.enter="onSendMessage()"></textarea>
@ -136,8 +144,7 @@
}
this.$store.commit("handleFileUpload", info);
},
beforeImageUpload(file) {
console.log(file);
handleImageBefore(file) {
let url = URL.createObjectURL(file);
let data = {
originUrl : url,
@ -160,6 +167,66 @@
// fileid
file.targetId = this.activeChat.targetId;
},
handleFileSuccess(res, file) {
console.log(res.data);
let data = {
name: file.name,
size: file.size,
url: res.data
}
let msgInfo = {
recvUserId: file.raw.targetId,
content: JSON.stringify(data),
type: 2
}
this.$http({
url: '/api/message/single/send',
method: 'post',
data: msgInfo
}).then(() => {
let info = {
targetId : file.raw.targetId,
fileId: file.raw.uid,
content: JSON.stringify(data),
loadStatus: "ok"
}
console.log(info);
this.$store.commit("handleFileUpload", info);
})
},
handleFileFail(res, file) {
let info = {
targetId : file.raw.targetId,
fileId: file.raw.uid,
loadStatus: "fail"
}
this.$store.commit("handleFileUpload", info);
},
handleFileBefore(file) {
let url = URL.createObjectURL(file);
let data = {
name: file.name,
size: file.size,
url: url
}
let msgInfo = {
fileId: file.uid,
sendUserId: this.$store.state.userStore.userInfo.id,
recvUserId: this.activeChat.targetId,
content: JSON.stringify(data),
sendTime: new Date().getTime(),
selfSend: true,
type: 2,
loadStatus: "loading"
}
//
this.$store.commit("insertMessage", msgInfo);
//
this.scrollToBottom();
// fileid
file.targetId = this.activeChat.targetId;
},
sendMessage(msgInfo) {
this.$http({
url: '/api/message/single/send',

Loading…
Cancel
Save