一、前言
由于项目需要根据不同机构,不同应用走不同的上传方式。整合完了做一个分享,需要的拿走
二、简要说明
基础应用表
@Data
@Alias("ImApplication")
@ApiModel("ImApplication")
public class ImApplication{
@ApiModelProperty(value = "应用")
private String id;
@ApiModelProperty(value = "机构id")
private String orgId;
@ApiModelProperty(value = "应用id")
private Long appId;
@ApiModelProperty(value = "SK")
private String secretKey;
@ApiModelProperty(value = "创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty("上传类型 0七牛 1腾讯云 2阿里云")
private Integer uploadType;
@ApiModelProperty("bucket空间")
private String uploadBucket;
@ApiModelProperty("公网访问地址")
private String uploadFilePath;
@ApiModelProperty("uploadAccessKey")
private String uploadAccessKey;
@ApiModelProperty("uploadSecretKey")
private String uploadSecretKey;
@ApiModelProperty("上传节点【腾讯云|阿里云】")
private String uploadEndpoint;
@ApiModelProperty("上传文件夹【腾讯云|阿里云】")
private String uploadFolder;
}
代码说明注意事项:
1.RedisUtil 是Redis工具根据项目使用的情况自行调整
2.NonePrintException 为项目自行封装的Exception 项目是做了全局拦截NonePrintException.目的是统一resultful api接口提示,自行参考修改
三、七牛云
maven引入,具体版本根据情况修改
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>[7.4.0, 7.4.99]</version>
</dependency>
七牛云上传工具类
/**
* 七牛云存储 工具
*/
@Slf4j
public class QiNiuManager{
private UploadManager uploadManager;
private BucketManager bucketManager;
private OperationManager operationManager;
private ImApplication imApplication;
public QiNiuManager(ImApplication imApplication) {
this.imApplication = imApplication;
com.qiniu.storage.Configuration cfg = new com.qiniu.storage.Configuration(getRegion());
uploadManager = new UploadManager(cfg);
Auth auth = getAuth();
operationManager = new OperationManager(auth, cfg);
}
private static final String KEY = "QINIU:REDIS:KEY";
private static final long EXP = 3600;//有效期秒
public String getToken(){
String key = KEY + imApplication.getAppId();
if(RedisUtil.hasKey(key)){
return RedisUtil.getValue(key);
}else{
Auth auth = getAuth();
StringMap putPolicy = new StringMap();
putPolicy.put("returnBody", "{"key":"$(key)","hash":"$(etag)","bucket":"$(bucket)","fsize":$(fsize)}");
String token = auth.uploadToken(imApplication.getUploadBucket(),null,EXP,putPolicy);
RedisUtil.putValue(key,token,EXP-(2*60), TimeUnit.SECONDS);
return token;
}
}
private Auth getAuth() {
return Auth.create(imApplication.getUploadAccessKey(), imApplication.getUploadSecretKey());
}
public QiniuPutRet upload(File file) throws NonePrintException {
return upload(file,null);
}
public QiniuPutRet upload(File file,String key) throws NonePrintException {
try {
Response response = uploadManager.put(file, key, getToken());
return new Gson().fromJson(response.bodyString(), QiniuPutRet.class);
} catch (QiniuException e) {
throw new NonePrintException("-79","云存储图片上传失败:"+e.getMessage());
}
}
public QiniuPutRet upload(byte[] uploadBytes) throws NonePrintException {
return upload(uploadBytes,null);
}
public QiniuPutRet upload(byte[] uploadBytes,String key) throws NonePrintException {
try {
Response response = uploadManager.put(uploadBytes, key, getToken());
return new Gson().fromJson(response.bodyString(), QiniuPutRet.class);
} catch (QiniuException e) {
throw new NonePrintException("-79","云存储图片上传失败:"+e.getMessage());
}
}
public QiniuPutRet upload(InputStream stream) throws NonePrintException {
return upload(stream,null);
}
public QiniuPutRet upload(InputStream stream,String key) throws NonePrintException {
try {
Response response = uploadManager.put(stream, key, getToken(),null,null);
return new Gson().fromJson(response.bodyString(), QiniuPutRet.class);
} catch (QiniuException e) {
throw new NonePrintException("-79","云存储图片上传失败:"+e.getMessage());
}
}
public void del(String key) {
try {
getBucketManager().delete(imApplication.getUploadBucket(),key);
} catch (QiniuException e) {
log.debug("七牛云删除图片失败"+key+e.getMessage());
ExceptionCenter.addException(e,"七牛云删除图片失败",key);
}
}
public BucketManager getBucketManager() {
if(BaseUtil.isEmpty(bucketManager)){
com.qiniu.storage.Configuration cfg = new com.qiniu.storage.Configuration(getRegion());
Auth auth = getAuth();
bucketManager = new BucketManager(auth,cfg);
}
return bucketManager;
}
public OperationManager getOperationManager(){
if(BaseUtil.isEmpty(operationManager)){
com.qiniu.storage.Configuration cfg = new com.qiniu.storage.Configuration(getRegion());
uploadManager = new UploadManager(cfg);
Auth auth = getAuth();
operationManager = new OperationManager(auth, cfg);
}
return operationManager;
}
public String getSaveAs(String newKey){
return UrlSafeBase64.encodeToString(imApplication.getUploadBucket() + ":" + newKey);
}
public String pfop(String key,String fops) throws QiniuException {
StringMap putPolicy = new StringMap();
putPolicy.put("pipeline", "mps-pipe"+key);
return getOperationManager().pfop(imApplication.getUploadBucket(), key, fops, putPolicy);
}
public OperationStatus getOperationStatus(String persistentId) throws QiniuException {
return getOperationManager().prefop(persistentId);
}
public FileInfo getFile(String key) throws QiniuException {
return getBucketManager().stat(imApplication.getUploadBucket(),key);
}
private Zone getRegion() {
Zone zone;
int type = Integer.parseInt(imApplication.getUploadEndpoint());
switch (type){
case 0:
zone = Zone.huadong();
break;
case 1:
zone = Zone.huabei();
break;
case 2:
zone = Zone.huanan();
break;
case 3:
zone = Zone.beimei();
break;
case 4:
zone = Zone.xinjiapo();
break;
default:
throw new NonePrintException("未知空间");
}
return zone;
}
}
使用方式
//工具内含有上传与删除,持久化等方法,具体可查看官方SDK进行拓展
QiNiuManager qiniuManager = new QiNiuManager(imApplication);
qiniuManager.upload(File file,String key)
qiniuManager.upload(byte[] uploadBytes)
qiniuManager.upload(byte[] uploadBytes,String key)
qiniuManager.upload(InputStream stream)
qiniuManager.upload(InputStream stream,String key)
qiniuManager.del(String key)
三、阿里云
maven引入,具体版本根据情况修改
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
阿里云Oss工具类
public class AliOssManager {
private ImApplication imApplication;
public AliOssManager(ImApplication imApplication) {
this.imApplication = imApplication;
}
public String doUpload(File file, String fileName){
// 创建OSSClient实例。
OSS ossClient = getOssClient();
String objectName = getObjectName(fileName);
try {
ossClient.putObject(imApplication.getUploadBucket(), objectName, file);
return objectName;
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
throw new NonePrintException("OSS上传失败:"+oe.getErrorMessage());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
throw new NonePrintException("OSS上传失败:"+ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
private String getObjectName(String fileName) {
return imApplication.getUploadFolder() + "/" + fileName;
}
private OSS getOssClient() {
return new OSSClientBuilder().build(imApplication.getUploadEndpoint(), imApplication.getUploadAccessKey(),imApplication.getUploadSecretKey());
}
public String doUpload(byte[] bytes, String fileName) {
OSS ossClient = getOssClient();
String objectName = getObjectName(fileName);
try {
ossClient.putObject(imApplication.getUploadBucket(), objectName, new ByteArrayInputStream(bytes));
return objectName;
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
throw new NonePrintException("OSS上传失败:"+oe.getErrorMessage());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
throw new NonePrintException("OSS上传失败:"+ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}
使用方式
new AliOssManager(imApplication).doUpload(file.getBytes(),fileName);
四、腾讯云
maven引入,具体版本根据情况修改
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.6.213</version>
</dependency>
腾讯云工具类
/**
* 腾讯云OSS上传
*/
@Slf4j
public class TencentOssManager {
private ImApplication imApplication;
public TencentOssManager(ImApplication imApplication) {
this.imApplication = imApplication;
}
public String doUpload(byte[] bytes, String fileName) {
TransferManager transferManager = createTransferManager();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
PutObjectRequest putObjectRequest = new PutObjectRequest(imApplication.getUploadBucket(), getObjectName(fileName), byteArrayInputStream,null);
Upload upload = transferManager.upload(putObjectRequest);
try {
UploadResult uploadResult = upload.waitForUploadResult();
log.debug("腾讯云OSS上传结果【{}】",JSON.toJSONString(uploadResult));
return uploadResult.getKey();
} catch (InterruptedException e) {
throw new NonePrintException("腾讯云OSS上传文件失败");
}finally {
IOUtil.closeQuietly(byteArrayInputStream);
transferManager.shutdownNow();
}
}
public String doUpload(File file, String fileName) {
TransferManager transferManager = createTransferManager();
PutObjectRequest putObjectRequest = new PutObjectRequest(imApplication.getUploadBucket(), getObjectName(fileName), file);
Upload upload = transferManager.upload(putObjectRequest);
try {
UploadResult uploadResult = upload.waitForUploadResult();
log.debug("腾讯云OSS上传结果【{}】",JSON.toJSONString(uploadResult));
return uploadResult.getKey();
} catch (InterruptedException e) {
throw new NonePrintException("腾讯云OSS上传文件失败");
}finally {
transferManager.shutdownNow();
}
}
private String getObjectName(String fileName) {
return imApplication.getUploadFolder() + "/" + fileName;
}
public TransferManager createTransferManager() {
// 创建一个 COSClient 实例,这是访问 COS 服务的基础实例。
// 详细代码参见本页: 简单操作 -> 创建 COSClient
COSClient cosClient = createCOSClient();
// 自定义线程池大小,建议在客户端与 COS 网络充足(例如使用腾讯云的 CVM,同地域上传 COS)的情况下,设置成16或32即可,可较充分的利用网络资源
// 对于使用公网传输且网络带宽质量不高的情况,建议减小该值,避免因网速过慢,造成请求超时。
ExecutorService threadPool = Executors.newFixedThreadPool(32);
// 传入一个 threadpool, 若不传入线程池,默认 TransferManager 中会生成一个单线程的线程池。
TransferManager transferManager = new TransferManager(cosClient, threadPool);
// 设置高级接口的配置项
// 分块上传阈值和分块大小分别为 5MB 和 1MB
TransferManagerConfiguration transferManagerConfiguration = new TransferManagerConfiguration();
transferManagerConfiguration.setMultipartUploadThreshold(5*1024*1024);
transferManagerConfiguration.setMinimumUploadPartSize(1*1024*1024);
transferManager.setConfiguration(transferManagerConfiguration);
return transferManager;
}
public COSClient createCOSClient(){
// 1 初始化用户身份信息(secretId, secretKey)。
COSCredentials cred = new BasicCOSCredentials(imApplication.getUploadAccessKey(), imApplication.getUploadSecretKey());
// 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
Region region = new Region(imApplication.getUploadEndpoint());
ClientConfig clientConfig = new ClientConfig(region);
// 这里建议设置使用 https 协议
clientConfig.setHttpProtocol(HttpProtocol.https);
// 3 生成 cos 客户端。
COSClient cosClient = new COSClient(cred, clientConfig);
return cosClient;
}
}
使用方式
new TencentOssManager(imApplication).doUpload(file.getBytes(),fileName)
五、整合上传
@PostMapping(value="doUpload")
@ApiOperation(value="上传文件")
public Result doUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletResponse response) throws Exception {
ImUser loginUser = getLoginUser();
ImApplication imApplication = imApplicationService.getImApplication(loginUser.getAppId());
if(BaseUtil.isEmpty(imApplication.getUploadType())){
throw new NonePrintException("您暂未配置存储空间,请先前往127.0.0.1配置");
}
response.addHeader("Access-Control-Allow-Origin", "*");
if(file.isEmpty()){
throw new NonePrintException("100","上传文件为空,请先选择需要上传的文件");
}
return addResult(ImUploadUtil.doUploadFile(file,imApplication,loginUser));
}
@Slf4j
public class ImUploadUtil {
public static FileMedia doUploadFile(CommonsMultipartFile file, ImApplication imApplication, ImUser loginUser) throws Exception {
String fileHash = UploadUtil.calculateFileHash(file);
FileMedia existMedia = UploadUtil.existFile(fileHash);
if(BaseUtil.isNotEmpty(existMedia)){
return existMedia;
}
String fileFileName = file.getOriginalFilename();
//上传的图片的类型
String fileType = fileFileName.substring(fileFileName.lastIndexOf(".") + 1).toLowerCase();
long fileSize = file.getSize();
//1、检查文件类型
String type = getWeixinFileType(fileType);
String msg = verifyFile(fileType, fileSize, type);
if(msg != null){
log.error("uploadFile 验证文件错误"+msg);
throw new NonePrintException("103",msg);
}
String newFileName = UUID.randomUUID().toString().replace("-", "").toLowerCase();
String imagePath = null;
FileMedia media = new FileMedia();
media.setUploadType(imApplication.getUploadType());
if(imApplication.getUploadType()==0){//七牛
QiniuPutRet putRet = new QiNiuManager(imApplication).upload(file.getBytes(),newFileName+"."+fileType);
imagePath = putRet.getKey();
}else if(imApplication.getUploadType()==1){//腾讯oss
imagePath = new TencentOssManager(imApplication).doUpload(file.getBytes(),newFileName+"."+fileType);
}else if(imApplication.getUploadType()==2){//阿里oss
imagePath = new AliOssManager(imApplication).doUpload(file.getBytes(),newFileName+"."+fileType);
}else{
throw new NonePrintException("暂未配置存储");
}
if (BaseUtil.isEmpty(imagePath)) {
throw new NonePrintException("104","上传失败");
}
media.setId(newFileName);
media.setType(type);
media.setSourceType(0);
media.setUrl(imApplication.getUploadFilePath()+File.separator+imagePath);
media.setFileSize((int)fileSize);
media.setFileName(fileFileName);
media.setCreatePerson(loginUser.getId());
media.setCreateTime(new Date());
media.setStatus(0);
media.setUpdateTime(new Date());
media.setFileExt(fileType.toUpperCase());
media.setFileSizeStr(convertFileSize(fileSize));
media.setSort(System.currentTimeMillis());
saveMedia(media);
return media;
}
public static void saveMedia(FileMedia media) throws IOException, NonePrintException {
UploadService uploadService = SpringContextUtil.getApplicationContext().getBean("FileMediaService", UploadService.class);
uploadService.insert(media);
}
public static boolean isImagesFile(String fileType) {
if(BaseUtil.isEmpty(fileType)) {
return false;
} else {
String[] fileTypes = new String[]{"jpg", "png", "gif", "bmp", "tif", "jpeg"};
for(int i = 0; i < fileTypes.length; ++i) {
if(fileType.equalsIgnoreCase(fileTypes[i])) {
return true;
}
}
return false;
}
}
public static String verifyFile(String fileType, long size, String type) {
/*if("image".equals(type)){
if (size > Configuration.UPLOAD_IMAGE_MAX) {
return "上传失败,图片文件不能超过" + Configuration.UPLOAD_IMAGE_MAX/1048576 + "M";
}
}
else if("voice".equals(type)){
if (size > Configuration.UPLOAD_VOICE_MAX) {
return "上传失败,声音文件不能超过" + Configuration.UPLOAD_VOICE_MAX/1048576 + "M";
}
}
else if("video".equals(type)){
if (size > Configuration.UPLOAD_VIDEO_MAX) {
return "上传失败,视频文件不能超过" + Configuration.UPLOAD_VIDEO_MAX/1048576 + "M";
}
}
else{
if (size > Configuration.UPLOAD_FILE_MAX) {
return "上传失败,上传文件不能超过" + Configuration.UPLOAD_FILE_MAX/1048576 + "M";
}
}*/
return null;
}
private static File multipartToFile(CommonsMultipartFile multfile) throws IOException {
String path = getProjectPath()+ "/"+multfile.getOriginalFilename();// 设定文件保存的目录
File f = new File(path);
File fileParent = f.getParentFile();
if(!fileParent.exists()){
fileParent.mkdirs();
}
multfile.transferTo(f);
return f;
}
public static String getWeixinFileType(String fileType) {
fileType = fileType.toLowerCase();
//图片
if(isImagesFile(fileType)){
return "image";
}
if("amr".equals(fileType)){
return "voice";
}
if("mp4".equals(fileType)||"flv".equals(fileType)||"mov".equals(fileType)||"avi".equals(fileType) ||"wmv".equals(fileType) || "ts".equals(fileType) || "mpg".equals(fileType)){
return "video";
}
return "file";
}
public static String getProjectPath() {
java.net.URL url = UploadUtil.class .getProtectionDomain().getCodeSource().getLocation();
String filePath = null ;
try {
filePath = java.net.URLDecoder.decode (url.getPath(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
}
if (filePath.indexOf(".jar")>-1) {
int startint=0;
if(filePath.indexOf("file:")>-1) {
startint = filePath.indexOf("file:") + 5 ;
}
filePath = filePath.substring(startint, filePath.lastIndexOf(".jar"));
filePath = filePath.substring(0, filePath.lastIndexOf("/") + 1);
}
File file = new File(filePath);
filePath = file.getAbsolutePath();
if(filePath.lastIndexOf("\")>=0){
return filePath.substring(0,filePath.lastIndexOf("\"));
}else{
return filePath.substring(0,filePath.lastIndexOf("/"));
}
}
public static String convertFileSize(long filesize){
String strUnit="Bytes";
String strAfterComma="";
int intDivisor=1;
if(filesize>=1073741824){
strUnit = "G";
intDivisor=1073741824;
}
else if(filesize>=1048576){
strUnit = "M";
intDivisor=1048576;
}
else if(filesize>=1024){
strUnit = "K";
intDivisor=1024;
}
if(intDivisor==1) return filesize + " " + strUnit;
strAfterComma = "" + 100 * (filesize % intDivisor) / intDivisor ;
if(strAfterComma=="") strAfterComma=".0";
return filesize / intDivisor + "." + strAfterComma + " " + strUnit;
}
}
FileMedia 为项目保存到数据库的记录,不需要保留的话 直接删除代码返回链接即可
public class FileMedia {
private String id;
private Date createTime;
private String createPerson;
private String type;
private Integer sourceType;
private String url;
private Integer fileSize;
private String fileName;
private Integer status;
private Date updateTime;
private String fileExt;
private String fileSizeStr;
private Long sort;
private Integer uploadType;
}