一.开发一个APP上传服务,需要有存储的支持,那么我们的解决方案将以下几种:
1. 1 直接将图片保存到服务的硬盘
- 1. 优点:开发便捷,成本低
- 2. 缺点:扩容困难
1.2 使用分布式文件系统进行存储
- 1. 优点:容易实现扩容
- 2. 缺点:开发复杂度稍大(尤其是开发复杂的功能)
1.3 使用nfs做存储
- 1. 优点:开发较为便捷
- 2. 缺点:需要有一定的运维知识进行部署和维护
1.4 使用第三方的存储服务
- 1. 优点:开发简单,拥有强大功能,免维护
- 2. 缺点:付费
在这我们采用第一、四解决方案,第三方服务选用阿里云的OSS服务。
二.配置
2.1 导入依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
2.2 编写aliyun.properties配置文件
aliyun.endpoint=
aliyun.accessKeyId=
aliyun.accessKeySecret=
aliyun.bucketName=
aliyun.urlPrefix=
2.3 编写AliyunConfig
@Configuration
@PropertySource(value = {"classpath:aliyun.properties"})
@ConfigurationProperties(prefix = "aliyun")
@Data
public class AliyunConfig {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
private String urlPrefix;
@Bean
public OSS oSSClient() {
return new OSSClient(endpoint, accessKeyId, accessKeySecret);
}
}
三.文件上传(图片,APP)
3.1 图片
// 允许上传的格式
private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg",
".jpeg", ".gif", ".png"};
3.2 APP-OSS
/**
* APK上传到阿里云oss
*
* @param request
* @return
*/
// @RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> upload(HttpServletRequest request) {
try {
MultipartHttpServletRequest fileRequest = (MultipartHttpServletRequest) request;
MultipartFile file = fileRequest.getFile("file");
InputStream inputStream = file.getInputStream();
String name = file.getOriginalFilename();
systemOperLogWrite.systemLogWrite("上传文件", SystemOperLog.LOG_TYPE_INSERT, systemOperLogWrite.objectToString(name));
//本地判断是否存在
String localMd5 = AliyunOSSClientUtil.getLocalMd5(file);
AppVersionVo vo = new AppVersionVo();
vo.setMd5(localMd5);
List<AppVersionEntity> appVersionEntities = appVersionDubboService.findByVo(vo);
if (CollectionUtils.isNotEmpty(appVersionEntities)) {
return ResultUtil.getFailResJson("该版本已存在", AcsConstent.BACK_FAILED_CODE);
}
String keyNeme = "";
if (StringUtils.isBlank(name)) {
return ResultUtil.getFailResJson("文件名不能为空");
}
if (name.endsWith(AcsConstent.APP.endWithName)) {
keyNeme = AcsConstent.APP.startFileName + StringUtils.getUUID() + AcsConstent.APP.endWithName;
} else {
return ResultUtil.getFailResJson(AcsConstent.APP.uploaFileNameError, AcsConstent.BACK_FAILED_CODE);
}
long size = 1;
if (file.getSize() > AcsConstent.INT_NUM_KB) {
size = file.getSize() / AcsConstent.INT_NUM_KB / AcsConstent.INT_NUM_KB;
}
// String bucketName = "aiot-face-image";
SystemConfigEntity systemConfigField = systemConfigDubboService.getSystemConfigField(Constants.Aliyun_BucketName);
String bucketName = systemConfigField.getValue();
// Endpoint以杭州为例,其它Region请按实际情况填写
// String endpoint = "http://oss-cn-shenzhen.aliyuncs.com";
SystemConfigEntity systemConfigField1 = systemConfigDubboService.getSystemConfigField(Constants.Aliyun_Endpoint);
String endpoint = systemConfigField1.getValue();
SystemConfigEntity accessKey = systemConfigDubboService.getSystemConfigField(Constants.Aliyun_AccessKeyId);
String accessKeyId = accessKey.getValue();
SystemConfigEntity accessSecret = systemConfigDubboService.getSystemConfigField(Constants.Aliyun_AccessKeySecret);
String accessKeySecret = AESUtil.aesDecrypt(accessSecret.getValue(), AcsConstent.APP.AccessKeySecret_DecryptKey);
// 创建OSSClient实例
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 文件大小
ObjectMetadata metadata = new ObjectMetadata();
// 上传的文件的长度
metadata.setContentLength(inputStream.available());
// 指定该Object被下载时的网页的缓存行为
metadata.setCacheControl("no-cache");
// 指定该Object下设置Header
metadata.setHeader("Pragma", "no-cache");
// 指定该Object被下载时的内容编码格式
metadata.setContentEncoding("utf-8");
// 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成
// 如果没有扩展名则填默认值application/octet-stream
metadata.setContentType(AliyunOSSClientUtil.getContentType(name));
// 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
PutObjectResult putResult = ossClient.putObject(bucketName, keyNeme, inputStream, metadata);
String eTag = putResult.getETag();
// 关闭OSSClient
ossClient.shutdown();
Date expiration = new Date(System.currentTimeMillis() + AcsConstent.APP.EXPIRE_DAY);
String url = ossClient.generatePresignedUrl(bucketName, keyNeme, expiration).toString();
JSONObject jsonObject = new JSONObject();
jsonObject.put("url", url);
jsonObject.put("MD5", eTag);
jsonObject.put("appSize", size);
return StringUtils.isNotBlank(url) ? ResultUtil.getSuccessResJson("data", jsonObject.toString()) : ResultUtil.getFailResJson("上传失败", "1");
} catch (Exception e) {
logger.info("上传文件失败###################{}", e);
}
return null;
}
3.2 APP-服务器
@RequestMapping(value = "/upload", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> uploadApk(HttpServletRequest request) {
FileOutputStream fileOutputStream = null;
InputStream inputStream = null;
try {
MultipartHttpServletRequest fileRequest = (MultipartHttpServletRequest) request;
MultipartFile file = fileRequest.getFile("file");
inputStream = file.getInputStream();
String fileName = file.getOriginalFilename();
//本地判断是否存在
String localMd5 = AliyunOSSClientUtil.fileToMd5(file);
JSONObject checkJson = checkPamams(localMd5, fileName);
if (checkJson != null) {
return checkJson;
}
long size = 1;
if (file.getSize() > AcsConstent.INT_NUM_KB) {
size = file.getSize() / AcsConstent.INT_NUM_KB / AcsConstent.INT_NUM_KB;
}
String downloadFileUrl = redisOperatorManager.getValue("upload.file.url", CommonConstants.SYSTEM_CONFIG_REDIS_INDEX, "http://%s:%s/acs-admin/system/fileManager/downloadFileByKey?key=%s");
downloadFileUrl = String.format(downloadFileUrl, host, port, localMd5);
String fileUploadPath = fileUploadBasePath + File.separator + "app";
File fileUploadPathFile = new File(fileUploadPath);
if (!fileUploadPathFile.exists()) {
fileUploadPathFile.mkdirs();
}
//新文件名为md5值
String keyName = localMd5 + AcsConstent.APP.endWithName;
String fileUploadFileName = fileUploadPath + File.separator + keyName;
File fileUploadFile = new File(fileUploadFileName);
if (!fileUploadFile.exists()) {
fileUploadFile.createNewFile();
}
fileOutputStream = new FileOutputStream(fileUploadFile);
IOUtils.copy(inputStream, fileOutputStream);
JSONObject jsonObject = new JSONObject();
jsonObject.put("url", downloadFileUrl);
jsonObject.put("MD5", localMd5);
jsonObject.put("appSize", size);
jsonObject.put("originalFilename", fileName);
FileUploadVo fileUploadVo = new FileUploadVo();
fileUploadVo.setFilePath(fileUploadPath);
fileUploadVo.setFileName(keyName);
fileUploadVo.setMd5(localMd5);
//通知
notifyFileUploadZk(fileUploadVo);
systemOperLogWrite.systemLogWrite("上传文件", SystemOperLog.LOG_TYPE_INSERT, jsonObject.toJSONString());
return ResultUtil.getSuccessResJson("data", jsonObject.toString());
} catch (RuntimeException e){
logger.info("运行时抛出异常###################{}", e);
} catch (Exception e) {
logger.info("上传文件失败###################{}", e);
} finally {
IOUtils.closeQuietly(fileOutputStream);
IOUtils.closeQuietly(inputStream);
}
return ResultUtil.getFailResJson("上传失败", "1");
}