step 1
配置文件:
##aliyun对象存储oss配置
aliyun.oss.access-key-id=访问阿里云API的密钥 在Access Key管理 里配置,最好配置个子账户的授权OSS所有权限即可。
aliyun.oss.access-key-secret=访问阿里云API的密钥 在Access Key管理 里配置,最好配置个子账户的授权OSS所有权限即可。
aliyun.oss.endpoint=http://oss-cn-beijing.aliyuncs.com(外网访问domain)
aliyun.oss.bucket-name=zhishoubao-test(填你bucket名称,也可以直接在程序里生成,即文件存放路径)
aliyun.oss.file-addr=http://file-test.zhishoubao.com(内网访问url)
aliyun.oss.max-file-size=10(文件最大限制)
#配置上传最大文件
spring.servlet.multipart.max-file-size=10mb(Multipart文件最大限制)
spring.servlet.multipart.max-request-size=10mb(Multipart文件最大限制)
package com.zhishoubao.ad.common.file.controller;
import com.aliyun.oss.ClientException;
import com.github.pagehelper.util.StringUtil;
import com.zhishoubao.ad.common.constant.errcode.ErrorCode;
import com.zhishoubao.ad.common.constant.properties.OssClientProperties;
import com.zhishoubao.ad.common.exception.ServiceException;
import com.zhishoubao.ad.common.file.service.ImageUploadService;
import com.zhishoubao.ad.common.file.dto.ImageUploadResult;
import com.zhishoubao.ad.common.file.utils.ImageTools;
import com.zhishoubao.ad.common.file.utils.VideoTools;
import com.zhishoubao.ad.common.utils.ArrayUtils;
import com.zhishoubao.ad.common.utils.FileUtils;
import com.zhishoubao.ad.common.utils.JsonUtils;
import com.zhishoubao.ad.common.utils.StringUtils;
import com.zhishoubao.ad.proxy.IAdInfoServiceProxy;
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.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author zy
* @date 2019-04-09
* @modify
* @copyright zhishoubao
*/
@CrossOrigin(value = "*", maxAge = 3600L)
@Slf4j
@Api(description = "文件操作", tags = "FileAPI")
@RestController
@RequestMapping("/file")
public class FileController {
private static final int CONS_1024 = 1024;
/**
* 图片格式
**/
private static final String[] EXTENSION_ARR = new String[]{"jpg", "png", "heic", "jpeg"};
/**
* 语音格式
**/
// private static final String[] VOICE_EXTENSION = new String[]{"mp3", "wma", "wav", "amr"};
/**
* 视频格式
**/
private static final String[] VIDEO_EXTENSION = new String[]{"mp4", "mov", "avi", "mpeg"};
/**
* 0:图片,2:视频
*/
private static final String[] SOURCE_TYPE = new String[]{"0", "2"};
@Autowired
private ImageUploadService imageUpload;
@Autowired
private OssClientProperties ossClientProperties;
@Autowired
private IAdInfoServiceProxy iAdInfoServiceProxy;
@ApiOperation(value = "上传文件", notes = "文件操作,需要授权Token,接口需要sourceType:(0:图片,2:视频),sourcePic:文件")
@PostMapping(value = "/upload/oss")
public String uploadFileLocal(HttpServletRequest request) throws Exception {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// // 页面图片元素的id
String sourceType = request.getParameter("sourceType");
if (StringUtil.isEmpty(sourceType) || !ArrayUtils.useLoop(SOURCE_TYPE, sourceType)) {
log.error("参数错误");
throw new ServiceException(ErrorCode.comm_param_error.getCode(),
ErrorCode.comm_param_error.getMessage());
}
MultipartFile file = multipartRequest.getFile("file");
if (file == null) {
log.error("文件不存在");
throw new ServiceException(ErrorCode.comm_file_notfound.getCode(),
ErrorCode.comm_file_notfound.getMessage());
}
Map<String, Object> resultMap = new HashMap<>(2);
String originalFilename = file.getOriginalFilename();
if (StringUtils.isEmpty(originalFilename)) {
log.error("文件无效");
throw new ServiceException(ErrorCode.comm_file_notwork.getCode(),
ErrorCode.comm_file_notwork.getMessage());
}
if (!checkExtension(file, sourceType)) {
log.error("文件格式或内容无效");
throw new ServiceException(ErrorCode.comm_fileStyle_notwork.getCode(),
ErrorCode.comm_fileStyle_notwork.getMessage());
}
//取md5加密后的中间16位
String fileMd5 = FileUtils.getMD5(file.getInputStream());
//MD5 加密后的位数有两种:16 位与 32 位。16 位实际上是从 32 位字符串中取中间的第 9 位到第 24 位的部分,用 Java 语言来说
String subMd5 = fileMd5.substring(8, 24);
Integer md5List = iAdInfoServiceProxy.selectAdMd5(subMd5);
if (md5List > 0) {
log.error("该文件已存在");
throw new ServiceException(ErrorCode.comm_file_already_exist.getCode(),
ErrorCode.comm_file_already_exist.getMessage());
}
//保存文件
String endpoint = ossClientProperties.getEndpoint();
String accessKeyId = ossClientProperties.getAccessKeyId();
String accessKeySecret = ossClientProperties.getAccessKeySecret();
String bucketName = ossClientProperties.getBucketName();
String fileAdd = ossClientProperties.getFileAddr();
String maxSizeStr = ossClientProperties.getMaxFileSize();
//默认限制2M
float maxSize = 10;
if (SOURCE_TYPE[0].equals(sourceType)) {
DecimalFormat df = new DecimalFormat("0.00");//设置保留位数
maxSize = Float.parseFloat(df.format((float) 800 / CONS_1024));
} else if (SOURCE_TYPE[1].equals(sourceType)) {
maxSize = 10;
}
try {
maxSize = Float.parseFloat(maxSizeStr);
} catch (NumberFormatException e) {
log.error("文件允许的大小设置不正确", e);
}
if (file.getSize() > (maxSize * CONS_1024 * CONS_1024)) {
log.error("上传的文件不能大于" + maxSize + "MB");
throw new ServiceException(ErrorCode.comm_file_super_large.getCode(), "上传的文件不能大于" + maxSize + "MB");
}
long fileSize = file.getSize();
String adWidth = null;
String adHeight = null;
String adDuration = null;
if (SOURCE_TYPE[0].equals(sourceType)) {
// adWidth = String.valueOf(ImageTools.getImgWidth(file));
// adHeight = String.valueOf(ImageTools.getImgHeight(file));
adDuration = "6";
}
if (SOURCE_TYPE[1].equals(sourceType)) {
// Map<String, Object> map = VideoTools.getVideoInfo(file);
// adWidth = map.get("adWidth").toString();
// adHeight = map.get("adHeight").toString();
// adDuration = map.get("adDuration").toString();
}
Map<String, Object> fileInfos = new HashMap<>(3);
fileInfos.put("adWidth", adWidth);
fileInfos.put("adHeight", adHeight);
fileInfos.put("adDuration", adDuration);
fileInfos.put("fileSize", fileSize);
return ossUploadFile(file, resultMap, originalFilename, fileAdd, endpoint,
accessKeyId,
accessKeySecret, bucketName, subMd5, fileInfos);
}
/**
* 校验图片格式和内容.
*
* @param file 图片
* @return boolean
*/
private boolean checkExtension(MultipartFile file, String sourceType) throws IOException {
String originalFilename = file.getOriginalFilename();
String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1).toLowerCase();
List<String> extensionList = null;
if (SOURCE_TYPE[0].equals(sourceType)) {
extensionList = Arrays.asList(EXTENSION_ARR);
} else if (SOURCE_TYPE[1].equals(sourceType)) {
extensionList = Arrays.asList(VIDEO_EXTENSION);
}
//后缀不符合要求
if (!extensionList.contains(fileExtension)) {
return false;
}
if (SOURCE_TYPE[0].equals(sourceType)) {
return isImage(file.getBytes());
}
return true;
}
/**
* 是否是合法图片
*
* @param imageContent 图片内容
* @return
*/
public boolean isImage(byte[] imageContent) {
if (imageContent == null || imageContent.length == 0) {
return false;
}
Image img;
InputStream is = null;
try {
is = new ByteArrayInputStream(imageContent);
img = ImageIO.read(is);
if (img == null || img.getWidth(null) <= 0
|| img.getHeight(null) <= 0) {
return false;
}
return true;
} catch (Exception e) {
return false;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
}
/**
* 上传文件到服务器.
*
* @param file 文件
* @param resultMap 返回结果
* @param originalFilename 文件名
* @param folder 文件夹
* @param endPoint 阿里云OSS endpoint
* @param accessKeyId 阿里云OSS accessKeyId
* @param accessKeySecret 阿里云OSS accessKeySecret
* @param bucket 阿里云OSS bucket
* @return String
*/
private String ossUploadFile(MultipartFile file, Map<String, Object> resultMap,
String originalFilename, String folder, String endPoint, String accessKeyId,
String accessKeySecret, String bucket, String subMd5, Map<String, Object> fileInfos) throws ServiceException {
try {
ImageUploadResult imageUploadResult = imageUpload
.imageUpload(file.getInputStream(), originalFilename, folder, endPoint, accessKeyId,
accessKeySecret, bucket);
resultMap.put("status", 0);
String domain = ossClientProperties.getFileAddr();
String address = imageUploadResult.getAddress();
resultMap.put("filePath", domain + "/" + address);
resultMap.put("fileName", address);
resultMap.put("subMd5", subMd5);
resultMap.put("fileInfos", fileInfos);
String resultJason = JsonUtils.toJson(resultMap);
return resultJason;
} catch (ClientException ce) {
throw new ServiceException(ErrorCode.comm_file_uploadFail.getCode(), ErrorCode.comm_file_uploadFail.getMessage(), ce);
} catch (Exception e) {
throw new ServiceException(ErrorCode.sys_hold_fail.getCode(), ErrorCode.sys_hold_fail.getMessage(), e);
}
}
}
package com.zhishoubao.ad.common.file.dto;
import java.io.Serializable;
/**
* 阿里云OSS图片上传返回结果.
*
* @author
* @version 1.0
*/
public class ImageUploadResult implements Serializable {
/**
* 图片服务器域名
*/
private String domain;
/**
* 图片相对地址
*/
private String address;
public ImageUploadResult() {
super();
}
public ImageUploadResult(String domain, String address) {
super();
this.domain = domain;
this.address = address;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package com.zhishoubao.ad.common.file.service;
import com.aliyun.oss.OSSClient;
import com.zhishoubao.ad.common.file.dto.ImageUploadResult;
import com.zhishoubao.ad.common.file.utils.OSSClientUntil;
import com.zhishoubao.ad.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import sun.rmi.runtime.Log;
import java.io.InputStream;
/**
* @author zy
* @ClassName: ImageUploadService
* @Description: 图片上传服务接口
* @date 2018年7月23日11:31:16
*/
@Slf4j
@Service
public class ImageUploadService {
/**
* OSS图片上传.
*
* @param file 文件
* @param fileName 文件名
* @param folder 文件夹
* @param endPoint 阿里云OSS endpoint
* @param accessKeyId 阿里云OSS accessKeyId
* @param accessKeySecret 阿里云OSS accessKeySecret
* @param bucket 阿里云OSS bucket
*/
public ImageUploadResult imageUpload(InputStream file, String fileName, String folder,
String endPoint, String accessKeyId, String accessKeySecret, String bucket)
throws Exception {
OSSClient ossClient = OSSClientUntil
.getInstance(endPoint, accessKeyId, accessKeySecret, bucket).getOssClient();
log.info("ossClient:{}", ossClient.toString());
String fileSuffix = fileName.substring(fileName.lastIndexOf("."));
String filePrefix = fileName.substring(0, fileName.lastIndexOf("."));
String md5FileName = StringUtils.getMD5Str(filePrefix);
String newFileName = md5FileName + fileSuffix;
// 设置文件路径和名称
fileName = String.format("%1$s/%2$s/%3$s", "ad", "tmp", newFileName);
ossClient.putObject(bucket, fileName, file);
log.info("ossClient:{}", ossClient.toString());
String domain = "http://" + bucket + "." + endPoint.substring(endPoint.lastIndexOf("/") + 1);
ImageUploadResult result = new ImageUploadResult(domain, fileName);
return result;
}
}
package com.zhishoubao.ad.common.file.utils;
import com.aliyun.oss.OSSClient;
/**
* 阿里云OSS客户端工具类.
*
* @author zy
* @since 2018年7月23日10:50:28
*/
public class OSSClientUntil {
private static OSSClientUntil instance = null;
private OSSClient ossClient = null;
private OSSClientUntil(String endpoint, String accessKeyId, String accessKeySecret,
String bucket) {
if (null == ossClient) {
ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
if (!ossClient.doesBucketExist(bucket)) {
ossClient.createBucket(bucket);
}
}
}
public static OSSClientUntil getInstance(String endpoint, String accessKeyId,
String accessKeySecret, String bucket) {
if (instance == null) {
instance = new OSSClientUntil(endpoint, accessKeyId, accessKeySecret, bucket);
}
return instance;
}
public OSSClient getOssClient() {
return ossClient;
}
}