Commit 0be86b8b authored by liqin's avatar liqin 💬

bug fixed

parent c5208255
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version> <version>2.4.4</version>
</parent> </parent>
<properties> <properties>
...@@ -127,7 +127,6 @@ ...@@ -127,7 +127,6 @@
<version>3.17</version> <version>3.17</version>
</dependency> </dependency>
<!-- Swagger2 Document --> <!-- Swagger2 Document -->
<dependency> <dependency>
<groupId>io.springfox</groupId> <groupId>io.springfox</groupId>
......
package cn.wisenergy.chnmuseum.party.common.dfs; package cn.wisenergy.chnmuseum.party.common.dfs;
import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException; import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException;
import cn.wisenergy.chnmuseum.party.common.util.CopyStreamUtils;
import cn.wisenergy.chnmuseum.party.common.util.FileTypeUtil; import cn.wisenergy.chnmuseum.party.common.util.FileTypeUtil;
import cn.wisenergy.chnmuseum.party.common.util.FileUtil; import cn.wisenergy.chnmuseum.party.common.util.FileUtil;
import com.github.tobato.fastdfs.domain.fdfs.FileInfo;
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
import com.github.tobato.fastdfs.domain.fdfs.StorePath; import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.fdfs.ThumbImageConfig; import com.github.tobato.fastdfs.domain.fdfs.ThumbImageConfig;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray; import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.exception.FdfsServerException;
import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -17,9 +22,10 @@ import javax.annotation.Resource; ...@@ -17,9 +22,10 @@ import javax.annotation.Resource;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.HashMap; import java.util.*;
import java.util.Map;
@Slf4j @Slf4j
@Component @Component
...@@ -66,17 +72,66 @@ public class FastDFSUtils { ...@@ -66,17 +72,66 @@ public class FastDFSUtils {
} }
public static String uploadFile(InputStream inputStream, long size, String fileName) { public static String uploadFile(InputStream inputStream, long size, String fileName) {
final StorePath storePath = storageClient.uploadFile(inputStream, size, FilenameUtils.getExtension(fileName), null); Map<String, Object> map = CopyStreamUtils.copyInputStream(inputStream);
String md5 = (String) map.get("md5");
InputStream is = (InputStream) map.get("inputStream");
final LinkedHashSet<MetaData> metaDataSet = new LinkedHashSet<>();
metaDataSet.add(new MetaData("fileName", "fileName"));
metaDataSet.add(new MetaData("fileSize", size + ""));
metaDataSet.add(new MetaData("fileExtName", FilenameUtils.getExtension(fileName)));
metaDataSet.add(new MetaData("MD5", md5));
final StorePath storePath = storageClient.uploadFile(is, size, FilenameUtils.getExtension(fileName), metaDataSet);
return dfsFileAccessBasePath + "/" + storePath.getFullPath(); return dfsFileAccessBasePath + "/" + storePath.getFullPath();
} }
/**
* 使用 FastDFS 提供的客户端 storageClient 来进行文件上传,最后将上传结果返回。
* 根据 groupName 和文件名获取文件信息。
*
* @param groupName
* @param path
* @return
*/
public static FileInfo getFileInfo(String groupName, String path) {
return storageClient.queryFileInfo(groupName, path);
}
/**
* 根据 groupName 和文件名获取文件信息。
*/
public static Set<MetaData> getFileMetaData(String fileUrl) {
fileUrl = fileUrl.replace(dfsFileAccessBasePath + "/", "");
String groupName = fileUrl.substring(0, fileUrl.indexOf("/"));
String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
return storageClient.getMetadata(groupName, path);
}
/** /**
* 下载文件(字节数组) * 下载文件(字节数组)
*/ */
public static byte[] downloadFile(String fileUrl) { public static byte[] downloadFile(String fileUrl) {
String group = fileUrl.substring(0, fileUrl.indexOf("/")); fileUrl = fileUrl.replace(dfsFileAccessBasePath + "/", "");
String groupName = fileUrl.substring(0, fileUrl.indexOf("/"));
String path = fileUrl.substring(fileUrl.indexOf("/") + 1); String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
return storageClient.downloadFile(group, path, new DownloadByteArray()); return storageClient.downloadFile(groupName, path, new DownloadByteArray());
}
/**
* 下载文件
*
* @param groupName
* @param path
* @return
*/
public static InputStream deleteFile(String groupName, String path) {
try {
return storageClient.downloadFile(groupName, path, inputStream -> inputStream);
} catch (FdfsServerException e) {
//不起作用
log.error("文件不存在,下载失败:" + e.getErrorCode());
throw new InterfaceException("文件不存在,下载失败:" + e.getErrorCode());
}
} }
/** /**
...@@ -101,6 +156,12 @@ public class FastDFSUtils { ...@@ -101,6 +156,12 @@ public class FastDFSUtils {
return new int[]{0, 0}; return new int[]{0, 0};
} }
private static ByteArrayOutputStream translateToByteArray(InputStream inputStream) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
IOUtils.copy(inputStream, out);
return out;
}
// private static class UploadFileSender implements UploadCallback { // private static class UploadFileSender implements UploadCallback {
// private final InputStream is; // private final InputStream is;
// //
......
package cn.wisenergy.chnmuseum.party.common.enums;
public enum FileTypeEnum {
IMAGE("Image", "图片"),
AUDIO("Audio", "音频"),
VIDEO("Video", "视频");
// 错误编码
private String type;
// 信息
private String name;
// 相应编码有参构造函数
FileTypeEnum(String type, String name) {
this.type = type;
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package cn.wisenergy.chnmuseum.party.common.enums;
/**
* 处理状态枚举
*
* @author mxy
* @date 2020/4/14
*/
public enum HANDLE_STATUS_ENUM {
SUCCESS("上传成功"),
FAILURE("上传失败");
/**
* 处理状态名称
*/
private String name;
HANDLE_STATUS_ENUM(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
...@@ -8,9 +8,9 @@ package cn.wisenergy.chnmuseum.party.common.enums; ...@@ -8,9 +8,9 @@ package cn.wisenergy.chnmuseum.party.common.enums;
*/ */
public enum RESULT_INFO_ENUM { public enum RESULT_INFO_ENUM {
RESULT_CODE("code", "响应码key"), RESULT_CODE("resultCode", "响应码key"),
RESULT_MSG("msg", "响应信息key"), RESULT_MSG("message", "响应结果信息"),
RESULT_BODY("body", "响应传输信息key"); RESULT_BODY("data", "响应结果数据");
/** /**
* 响应结果key * 响应结果key
......
...@@ -14,6 +14,17 @@ public class InterfaceException extends RuntimeException { ...@@ -14,6 +14,17 @@ public class InterfaceException extends RuntimeException {
// 错误编码信息 // 错误编码信息
private String errorMsg; private String errorMsg;
/**
* 应用接口有参构造函数
*
* @param errorMsg 错误信息
*/
public InterfaceException(String errorMsg) {
super(" errorMsg:" + errorMsg);
this.errorCode = "500";
this.errorMsg = errorMsg;
}
/** /**
* 应用接口有参构造函数 * 应用接口有参构造函数
* *
......
package cn.wisenergy.chnmuseum.party.common.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class CopyStreamUtils {
/**
* @param inputStream
* @return
*/
public static Map<String, Object> copyInputStream(InputStream inputStream) {
/*
* 因为inputStream只能读取一次,
* 所以将其进行复制
* 复制方法是通过定义一个byteArrayOutputStream
* 然后将byteArrayOutputStream转化为InputStream
* 但是这样存在一个问题,就是当文件比较大的时候,会出现内存溢出
* 将jvm参数调整也效果不佳
* 所以解决方案为采用分段的方法,将原本的inputStream分成很多小的inputStream
* 然后通过SequenceInputStream进行合并输入流
* 合并后的SequenceInputStream和原来的输入流相同,达到复制的效果
*
*/
ByteArrayOutputStream baos;
// 每次读取1024字节
byte[] buffer = new byte[1024];
int readNum;
// 定义一个Vector,用来存储分段后的小的InputStream,最后用于构造SequenceInputStream和并流
Vector<InputStream> streams = new Vector<>();
// 为提高效率,在此处进行流处理的时候,直接进行md5校验码的生成,节省资源
String MD5String = "";
InputStream sequenceInputStream = null;
try {
while ((readNum = inputStream.read(buffer)) > -1) {
baos = new ByteArrayOutputStream();
baos.write(buffer, 0, readNum);
// 更新md5校验码的输入流
Md5Utils.updateFileMD5String(buffer, readNum);
// 分段的复制inputStream,每次将新产生的小段流与原来的合并
streams.add(new ByteArrayInputStream(baos.toByteArray()));
// 不同于其他输出流,二进制流无法通过flush进行刷新,所以只能通过close之后再重新new来充值二进制流
baos.close();
}
// 生成md5校验码
MD5String = Md5Utils.getFileMD5String();
// 通过之前的分段的小的inputStream进行构造合并流
Enumeration<InputStream> e = streams.elements();
sequenceInputStream = new SequenceInputStream(e);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, Object> map = new HashMap<>();
map.put("md5", MD5String);
map.put("inputStream", sequenceInputStream);
return map;
}
}
\ No newline at end of file
...@@ -15,7 +15,7 @@ public class FileTypeUtil { ...@@ -15,7 +15,7 @@ public class FileTypeUtil {
private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>(); private static final Map<String, String> FILE_TYPE_MAP = new HashMap<>();
private static final List<String> imageAllowFiles = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp");/* 允许上传的图片格式 */ private static final List<String> imageAllowFiles = Arrays.asList("png", "jpg", "jpeg", "gif", "bmp", "tif");/* 允许上传的图片格式 */
static { static {
getAllFileType(); // 初始化文件类型信息 getAllFileType(); // 初始化文件类型信息
......
package cn.wisenergy.chnmuseum.party.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Md5Utils {
private static final Logger logger = LoggerFactory.getLogger(Md5Utils.class);
protected static char[] hexDegists = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
protected static MessageDigest md5 = null;
static {
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsae) {
logger.info(Md5Utils.class.getName() + "初始化失败,MessageDigest不支持md5!");
nsae.printStackTrace();
}
}
/**
* 获取md5校验码
*
* @param inputStream
* @return
* @throws IOException
*/
public static String getFileMD5String(java.io.InputStream inputStream) throws IOException {
// 每次读取1024字节
byte[] buffer = new byte[1024];
int readNum = 0;
while ((readNum = inputStream.read(buffer)) > 0) {
md5.update(buffer, 0, readNum);
}
inputStream.close();
return bufferToHex(md5.digest());
}
/**
* 更新需要校验的文件输入流
*
* @param bs
* @return
* @throws IOException
*/
public static void updateFileMD5String(byte[] bs, int readNum) {
// 每次读取bs字节,更新MD5输入流
md5.update(bs, 0, readNum);
}
/**
* 返回md5校验码
*
* @return
* @throws IOException
*/
public static String getFileMD5String() {
return bufferToHex(md5.digest());
}
private static String bufferToHex(byte[] bytes) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte[] bytes, int m, int n) {
StringBuffer stringBuffer = new StringBuffer(n * 2);
int k = m + n;
for (int i = m; i < k; i++) {
appendHexPair(bytes[i], stringBuffer);
}
return stringBuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringBuffer) {
// 取字节中高四位进行转换
char ch0 = hexDegists[(bt & 0xf0) >> 4];
// 取字节中低四位进行转换
char ch1 = hexDegists[(bt & 0xf)];
stringBuffer.append(ch0);
stringBuffer.append(ch1);
}
}
package cn.wisenergy.chnmuseum.party.common.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 批量操作响应结果
*
* @author mxy
* @date 2020/4/22
*/
@Data
@Accessors(chain = true)
@ApiModel(value = "批量操作响应参数", description = "批量操作响应参数")
public class BatchUploadResVO {
private static final long serialVersionUID = 51873394122822866L;
@ApiModelProperty("成功数量")
private int successCount;
@ApiModelProperty("失败数量")
private int failureCount;
@ApiModelProperty("操作总数")
private int total;
@ApiModelProperty("处理结果集合")
private List<HandleResult> handleList;
@ApiModelProperty("成功上传的URL集合")
private List<String> urlList;
@Data
public static class HandleResult {
@ApiModelProperty("名称")
private String fileName;
@ApiModelProperty("类型")
private String fileType;
@ApiModelProperty("文件URL")
private String fileUrl;
@ApiModelProperty("处理结果")
private String handleResult;
@ApiModelProperty("处理结果描述")
private String description;
}
}
package cn.wisenergy.chnmuseum.party.common.vo;
public class ImageUploadResult {
private Integer statusCode;
private String url;
private String width;
private String height;
private String fileExtName;
private Long fileSize;
private String fileName;
public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
public String getFileExtName() {
return fileExtName;
}
public void setFileExtName(String fileExtName) {
this.fileExtName = fileExtName;
}
public Long getFileSize() {
return fileSize;
}
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
package cn.wisenergy.chnmuseum.party.common.vo;
public class PicUploadResult {
private Integer error;
private String url;
private String width;
private String height;
public Integer getError() {
return error;
}
public void setError(Integer error) {
this.error = error;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getWidth() {
return width;
}
public void setWidth(String width) {
this.width = width;
}
public String getHeight() {
return height;
}
public void setHeight(String height) {
this.height = height;
}
}
...@@ -21,5 +21,7 @@ public class VideoVo { ...@@ -21,5 +21,7 @@ public class VideoVo {
private String language; private String language;
private String md5;
} }
...@@ -12,6 +12,7 @@ import javax.validation.constraints.NotBlank; ...@@ -12,6 +12,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
/** /**
* <p> * <p>
...@@ -92,4 +93,8 @@ public class Asset implements Serializable { ...@@ -92,4 +93,8 @@ public class Asset implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private String assetCopyrightOwnerName; private String assetCopyrightOwnerName;
@ApiModelProperty("视频URL列表")
@TableField(exist = false)
private List<String> videoUrlList;
} }
...@@ -2,12 +2,10 @@ package cn.wisenergy.chnmuseum.party.web.controller; ...@@ -2,12 +2,10 @@ package cn.wisenergy.chnmuseum.party.web.controller;
import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils; import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils;
import cn.wisenergy.chnmuseum.party.common.enums.AuditStatusEnum; import cn.wisenergy.chnmuseum.party.common.enums.AuditStatusEnum;
import cn.wisenergy.chnmuseum.party.common.enums.RESPONSE_CODE_ENUM;
import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException;
import cn.wisenergy.chnmuseum.party.common.validator.groups.Add; import cn.wisenergy.chnmuseum.party.common.validator.groups.Add;
import cn.wisenergy.chnmuseum.party.common.validator.groups.Update; import cn.wisenergy.chnmuseum.party.common.validator.groups.Update;
import cn.wisenergy.chnmuseum.party.common.vo.VideoVo;
import cn.wisenergy.chnmuseum.party.common.vo.GenericPageParam; import cn.wisenergy.chnmuseum.party.common.vo.GenericPageParam;
import cn.wisenergy.chnmuseum.party.common.vo.VideoVo;
import cn.wisenergy.chnmuseum.party.model.Asset; import cn.wisenergy.chnmuseum.party.model.Asset;
import cn.wisenergy.chnmuseum.party.model.AssetType; import cn.wisenergy.chnmuseum.party.model.AssetType;
import cn.wisenergy.chnmuseum.party.model.CopyrightOwner; import cn.wisenergy.chnmuseum.party.model.CopyrightOwner;
...@@ -20,26 +18,23 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; ...@@ -20,26 +18,23 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* <pre> * <pre>
...@@ -64,25 +59,23 @@ public class AssetController extends BaseController { ...@@ -64,25 +59,23 @@ public class AssetController extends BaseController {
@Resource @Resource
private AssetTypeService assetTypeService; private AssetTypeService assetTypeService;
@ApiImplicitParams({ @PostMapping(value = "/save")
//@ApiImplicitParam(name = "files", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat="array", allowMultiple = true)
})
@PostMapping(value = "/save",
headers = "content-type=multipart/form-data",
consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@RequiresPermissions("asset:save") @RequiresPermissions("asset:save")
@ApiOperation(value = "添加视频", notes = "添加视频") @ApiOperation(value = "添加视频", notes = "添加视频")
public Map<String, Object> saveAsset(@Validated(value = {Add.class}) Asset asset, @RequestPart(value = "files", required = false) MultipartFile[] files) throws IOException { public Map<String, Object> saveAsset(@Validated(value = {Add.class}) Asset asset) {
if (files.length == 0) { final List<VideoVo> filesMetadata = new ArrayList<>(asset.getVideoUrlList().size());
throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "视频必须上传");
} final List<String> videoUrlList = asset.getVideoUrlList();
final List<VideoVo> filesMetadata = new ArrayList<>(2); for (String videoUrl : videoUrlList) {
for (MultipartFile file : files) {
// 原始文件名 // 原始文件名
String originalFilename = file.getOriginalFilename(); final Set<MetaData> metaData = FastDFSUtils.getFileMetaData(videoUrl);
String url = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename); String fileName = metaData.stream().filter(x -> "fileName".equals(x.getName())).map(MetaData::getValue).findFirst().get();
filesMetadata.add(VideoVo.builder().fileName(originalFilename).fileExtName(FilenameUtils.getExtension(originalFilename)) Long fileSize = metaData.stream().filter(x -> "fileSize".equals(x.getName())).map(MetaData::getValue).map(Long::parseLong).findFirst().get();
.fileSize(file.getSize()).fileUrl(url).build()); String fileExtName = metaData.stream().filter(x -> "fileExtName".equals(x.getName())).map(MetaData::getValue).findFirst().get();
String md5 = metaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get();
filesMetadata.add(VideoVo.builder().fileName(fileName)
.fileExtName(fileExtName)
.fileSize(fileSize).fileUrl(videoUrl).md5(md5).build());
} }
asset.setVideoUrl(JSONObject.toJSONString(filesMetadata)); asset.setVideoUrl(JSONObject.toJSONString(filesMetadata));
asset.setAuditStatusAdd(AuditStatusEnum.TBC.name()); asset.setAuditStatusAdd(AuditStatusEnum.TBC.name());
...@@ -91,26 +84,28 @@ public class AssetController extends BaseController { ...@@ -91,26 +84,28 @@ public class AssetController extends BaseController {
// 返回操作结果 // 返回操作结果
if (result) { if (result) {
return getSuccessResult(); return getSuccessResult();
} else {
// 保存失败
return getFailResult();
} }
return getFailResult();
} }
@PutMapping("/update") @PutMapping("/update")
@RequiresPermissions("asset:update") @RequiresPermissions("asset:update")
@ApiOperation(value = "修改视频信息", notes = "修改视频信息") @ApiOperation(value = "修改视频信息", notes = "修改视频信息")
public Map<String, Object> updateAsset(@Validated(value = {Update.class}) Asset asset, @RequestParam(value = "files") MultipartFile[] files) throws IOException { public Map<String, Object> updateAsset(@Validated(value = {Update.class}) Asset asset) {
if (files.length > 0) { final List<VideoVo> filesMetadata = new ArrayList<>(asset.getVideoUrlList().size());
final Map<String, String> filesMetadata = new LinkedHashMap<>(2); final List<String> videoUrlList = asset.getVideoUrlList();
for (MultipartFile file : files) { for (String videoUrl : videoUrlList) {
// 上传简单文件名 // 原始文件名
String originalFilename = file.getOriginalFilename(); final Set<MetaData> metaData = FastDFSUtils.getFileMetaData(videoUrl);
String url = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename); String fileName = metaData.stream().filter(x -> "fileName".equals(x.getName())).map(MetaData::getValue).findFirst().get();
filesMetadata.put(originalFilename.trim(), url); Long fileSize = metaData.stream().filter(x -> "fileSize".equals(x.getName())).map(MetaData::getValue).map(Long::parseLong).findFirst().get();
} String fileExtName = metaData.stream().filter(x -> "fileExtName".equals(x.getName())).map(MetaData::getValue).findFirst().get();
asset.setAuditStatusAdd(AuditStatusEnum.TBC.name()); String md5 = metaData.stream().filter(x -> "MD5".equals(x.getName())).map(MetaData::getValue).findFirst().get();
filesMetadata.add(VideoVo.builder().fileName(fileName)
.fileExtName(fileExtName)
.fileSize(fileSize).fileUrl(videoUrl).md5(md5).build());
} }
asset.setVideoUrl(JSONObject.toJSONString(filesMetadata));
asset.setAuditStatusAdd(AuditStatusEnum.TBC.name()); asset.setAuditStatusAdd(AuditStatusEnum.TBC.name());
boolean flag = assetService.updateById(asset); boolean flag = assetService.updateById(asset);
if (flag) { if (flag) {
......
package cn.wisenergy.chnmuseum.party.web.controller; package cn.wisenergy.chnmuseum.party.web.controller;
import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils; import cn.wisenergy.chnmuseum.party.common.dfs.FastDFSUtils;
import cn.wisenergy.chnmuseum.party.common.vo.PicUploadResult; import cn.wisenergy.chnmuseum.party.common.enums.FileTypeEnum;
import org.slf4j.Logger; import cn.wisenergy.chnmuseum.party.common.enums.HANDLE_STATUS_ENUM;
import org.slf4j.LoggerFactory; import cn.wisenergy.chnmuseum.party.common.enums.RESPONSE_CODE_ENUM;
import cn.wisenergy.chnmuseum.party.common.mvc.InterfaceException;
import cn.wisenergy.chnmuseum.party.common.vo.BatchUploadResVO;
import cn.wisenergy.chnmuseum.party.common.vo.ImageUploadResult;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/** /**
* 图片上传 * <p>
* 文件上传 前端控制器
* </p>
*
* @author Danny Lee
* @since 2021-03-16
*/ */
@Slf4j
@RestController @RestController
@RequestMapping("/pic") @RequestMapping("/file")
public class PicUploadController { public class FileUploadController {
private static final Logger log = LoggerFactory.getLogger(PicUploadController.class); // 允许上传的格式
private static final String[] IMAGE_TYPE = new String[]{"JPG", "JPEG", "PNG", "BMP", "WBMP"};
// 允许上传的格式 // 允许上传的格式
private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".png"}; private static final String[] VIDEO_TYPE = new String[]{"MP4", "FLV"};
// @RequestMapping(value = "/upload", method = RequestMethod.POST) // @RequestMapping(value = "/upload", method = RequestMethod.POST)
// public ResponseEntity<PicUploadResult> upload(@RequestParam(value = "bc_cover", required = true) MultipartFile uploadFile, HttpServletResponse response) throws Exception { // public ResponseEntity<PicUploadResult> upload(@RequestParam(value = "bc_cover", required = true) MultipartFile uploadFile, HttpServletResponse response) throws Exception {
...@@ -74,15 +95,91 @@ public class PicUploadController { ...@@ -74,15 +95,91 @@ public class PicUploadController {
// return ResponseEntity.status(HttpStatus.CREATED).body(fileUploadResult); // return ResponseEntity.status(HttpStatus.CREATED).body(fileUploadResult);
// } // }
@RequestMapping(value = "/upload", method = RequestMethod.POST) @PostMapping(value = "/image/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<PicUploadResult> uploadFile(@RequestParam(value = "cover") MultipartFile uploadFile) throws Exception { public ResponseEntity<ImageUploadResult> uploadFile(@RequestParam(value = "cover") MultipartFile uploadFile) throws Exception {
PicUploadResult fileUploadResult = new PicUploadResult(); if (uploadFile == null || uploadFile.getSize() == 0) {
String filePath = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), uploadFile.getOriginalFilename()); throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "没有文件可供上传");
if (log.isDebugEnabled()) { }
log.debug("Pic file upload .[{}] to [{}] .", uploadFile.getOriginalFilename(), filePath); String fileName = uploadFile.getOriginalFilename();
String extension = FilenameUtils.getExtension(fileName);
if (StringUtils.isBlank(extension)) {
throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "文件格式不支持");
}
boolean anyMatch = Arrays.stream(IMAGE_TYPE).anyMatch(s -> Objects.equals(s, extension.toUpperCase()));
if (!anyMatch) {
throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "文件格式不支持");
}
String url = FastDFSUtils.uploadFile(uploadFile.getInputStream(), uploadFile.getSize(), fileName);
ImageUploadResult imageUploadResult = new ImageUploadResult();
imageUploadResult.setFileName(fileName);
imageUploadResult.setFileExtName(extension);
imageUploadResult.setFileSize(uploadFile.getSize());
imageUploadResult.setUrl(url);
return ResponseEntity.status(HttpStatus.CREATED).body(imageUploadResult);
}
@ApiImplicitParams({
@ApiImplicitParam(name = "files", value = "视频文件", paramType = "form", dataType = "__file", collectionFormat = "array", allowMultiple = true)
})
@PostMapping(value = "/video/upload", headers = "content-type=multipart/form-data", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@RequiresPermissions("video:upload")
@ApiOperation(value = "多视频上传", notes = "多视频上传")
public ResponseEntity<BatchUploadResVO> uploadFile(@RequestPart(value = "files", required = false) MultipartFile[] files) throws IOException {
if (files.length == 0) {
throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "没有文件可供上传");
} }
fileUploadResult.setUrl(filePath); final boolean matchChinese = Arrays.stream(files).anyMatch(s -> Objects.requireNonNull(s.getOriginalFilename()).contains("中文"));
return ResponseEntity.status(HttpStatus.CREATED).body(fileUploadResult); if (!matchChinese) {
throw new InterfaceException(RESPONSE_CODE_ENUM.REQUEST_PARAMS_ERROR.getCode(), "必须包含中文视频");
}
int successCount = 0;
int failureCount = 0;
List<BatchUploadResVO.HandleResult> handleList = new ArrayList<>();
List<String> videoUrlList = new ArrayList<>();
for (MultipartFile file : files) {
// 当前维度表下线结果
BatchUploadResVO.HandleResult handleResult = new BatchUploadResVO.HandleResult();
// 原始文件名
String originalFilename = file.getOriginalFilename();
if (StringUtils.isBlank(originalFilename)) {
handleResult.setFileName("");
handleResult.setFileType(FileTypeEnum.VIDEO.getName());
handleResult.setFileUrl("");
handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
handleResult.setDescription("文件名为空");
failureCount++;
continue;
}
handleResult.setFileName(originalFilename);
handleResult.setFileType(FileTypeEnum.VIDEO.getName());
handleResult.setHandleResult(HANDLE_STATUS_ENUM.FAILURE.getName());
boolean anyMatch = Arrays.stream(VIDEO_TYPE).anyMatch(s -> Objects.equals(s, FilenameUtils.getExtension(originalFilename).toUpperCase()));
if (anyMatch) {
String url = FastDFSUtils.uploadFile(file.getInputStream(), file.getSize(), originalFilename);
handleResult.setFileUrl(url);
handleResult.setDescription("操作成功");
videoUrlList.add(url);
successCount++;
} else {
handleResult.setFileUrl("");
handleResult.setDescription("文件格式不支持");
failureCount++;
}
// 设置处理的业务表信息
handleList.add(handleResult);
}
BatchUploadResVO batchUploadResVO = new BatchUploadResVO();
batchUploadResVO.setFailureCount(failureCount);
batchUploadResVO.setSuccessCount(successCount);
batchUploadResVO.setTotal(files.length);
batchUploadResVO.setHandleList(handleList);
batchUploadResVO.setUrlList(videoUrlList);
return ResponseEntity.status(HttpStatus.CREATED).body(batchUploadResVO);
} }
} }
...@@ -58,6 +58,7 @@ public class BaseController implements Serializable { ...@@ -58,6 +58,7 @@ public class BaseController implements Serializable {
protected Map<String, Object> getResult(Object obj) { protected Map<String, Object> getResult(Object obj) {
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put(RESULT_INFO_ENUM.RESULT_CODE.getKey(), RESPONSE_CODE_ENUM.REQUEST_SUCCESS.getCode()); map.put(RESULT_INFO_ENUM.RESULT_CODE.getKey(), RESPONSE_CODE_ENUM.REQUEST_SUCCESS.getCode());
map.put(RESULT_INFO_ENUM.RESULT_MSG.getKey(), RESPONSE_CODE_ENUM.REQUEST_SUCCESS.getMsg());
map.put(RESULT_INFO_ENUM.RESULT_BODY.getKey(), obj); map.put(RESULT_INFO_ENUM.RESULT_BODY.getKey(), obj);
return map; return map;
} }
......
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