写在前面:
还记得首次在第一家实习单位,项目中用到了文件上传下载。腾哥说用OSS,接着便问我有没有使用过阿里云的OSS服务。当时一脸懵,啥是OSS服务??它能干啥??怎么用??之前总感觉一个系统中要是没有文件上传下载功能就称不上是一个系统。到现在为止,所做过的业务中更是不可或缺。使用阿里云OSS服务,大大减轻了开发压力,稍加配置便能轻松上手。既然用的这么频繁,那就记录一下咯。
1.开通阿里云OSS服务
https://common-buy.aliyun.com/?spm=5176.208357.1107607.10.5e73390fav1TpM&commodityCode=ossbag&request=%7B%22region%22%3A%22china-common%22%7D#/buy
主要还是为了演示以及学习,所以就按照价格最便宜的来吧~
2.创建存储空间
购买成功,进入OSS控制台。
在Bucket列表右侧选择,创建Bucket(存储空间)
创建成功。则会在左侧“我的访问路径”中就能看到刚才自己新建的Bucket。
创建一个访问控制的RAM账号和密码
填写完整,输入手机验证码。会得到accessKeyId和accessKeySecret。记得保存,只会此时展示一次,想在得到就获取不到了。
3.上传文件
利用OSSJava SDK来上传文件。
1.配置pom.xml
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
2. 配置application.yml
#存储本地
upload:
path: F://
#下载本地
downLoad:
path: G://
#OSS服务
entFile:
endpoint: http://oss-cn-hangzhou.aliyuncs.com
accessKeyId: XXXXXXXXXX
accessKeySecret: YYYYYYYYY
bucketName: tianhong-bucket
#访问(下载)请求头
access: http://tianhong-bucket.oss-cn-hangzhou.aliyuncs.com/
accessKeyId& accessKeySecret:访问控制的RAM账号和密码
EndPoint(地域节点):在创建Bucket时选择的区域对应的便是杭州节点(华东1(杭州))
Access:访问域名带上文件路径,即可通过互联网访问到 Bucket 内的任意文件。
Ps:我这里将Bucket ACL设置为了公共读。若是私有,则需要在Header或Url中包含签名。
3.GlobalConfig获取配置文件中OSS属性信息
//===================阿里云OSS配置===================
@Value("${entFile.endpoint}")
private String entFileEndpoint;
@Value("${entFile.accessKeyId}")
private String entFileAccessKeyId;
@Value("${entFile.accessKeySecret}")
private String entFileAccessKeySecret;
@Value("${entFile.bucketName}")
private String entFileBucketName;
@Value("${entFile.access}")
private String entFileAccess;
//===================上传、下载地址===================
@Value("${upload.path}")
private String uploadPath;
@Value("${downLoad.path}")
private String downLoadPath;
//=====================阿里云OSS配置=================
public static String ENDPOINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
public static String ACCESS;
//===================上传、下载地址===================
public static String UPLOAD_PATH;
public static String DOWNLOAD_PATH;
@Override
public void afterPropertiesSet() throws Exception {
//======阿里云OSS配置=========
ENDPOINT = entFileEndpoint;
ACCESS_KEY_ID = entFileAccessKeyId;
ACCESS_KEY_SECRET = entFileAccessKeySecret;
BUCKET_NAME = entFileBucketName;
ACCESS = entFileAccess;
//======上传、下载地址=========
UPLOAD_PATH = uploadPath;
DOWNLOAD_PATH = downLoadPath;
}
4.OssService做成一个Service方便后期进行对其调用
public interface OssService {
//文件上传
String uploadFile(File file);
}
5.OssServiceImpl参考API实现其内部逻辑
主要是根据配置文件中OSS一些属性,创建存储空间。先判断存储空间是否存在,不存在则新建。接着便创建文件路径及文件名称。最后,上传文件到指定的存储空间(bucketName)并将其保存为指定的文件名称(objectName)。
@Slf4j
@Service("ossService")
public class OssServiceImpl implements OssService {
//文件上传
@Override
public String uploadFile(File file) {
String endpoint = GlobalConfig.ENDPOINT;
String accessKeyId = GlobalConfig.ACCESS_KEY_ID;
String accessKeySecret = GlobalConfig.ACCESS_KEY_SECRET;
String bucketName = GlobalConfig.BUCKET_NAME;
log.info("=========>OSS文件上传开始:" + file.getName());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = simpleDateFormat.format(new Date());
if (null == file) {
return null;
}
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
try {
//容器不存在,就创建
if (!ossClient.doesBucketExist(bucketName)) {
ossClient.createBucket(bucketName);
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
ossClient.createBucket(createBucketRequest);
}
//创建文件路径
String fileUrl = bucketName + "/" + (dateStr + "/" + UUID.randomUUID().toString().replace("-", "") + "-" + file.getName());
//上传文件
PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, file));
//设置权限 这里是公开读
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
if (null != result) {
log.info("==========>OSS文件上传成功,OSS地址:-------------------------" + fileUrl);
return fileUrl;
}
} catch (OSSException oe) {
log.error(oe.getMessage());
} catch (ClientException ce) {
log.error(ce.getMessage());
} finally {
//关闭
ossClient.shutdown();
}
return null;
}
}
6. 举例说明
做一个文件上传的Controller。上传一个文件。
@RequestMapping("/oss")
@RestController
public class OssController {
@Value("${upload.path}")
private String uploadPath;
@Value("${downLoad.path}")
private String downLoadPath;
@Autowired
private OssService ossService;
//文件上传
@PostMapping("/upload")
public WebResponse upload(MultipartFile file) throws IOException {
File fileLocal = new File(uploadPath, UUID.randomUUID().toString().substring(0, 6) + "-" + file.getOriginalFilename());
//将建好的文件用流的形式读写进去 并会下载一份到本地
FileUtils.copyInputStreamToFile(file.getInputStream(), fileLocal);
String ossUrl = ossService.uploadFile(fileLocal);
return WebResponse.resSuccess("上传成功", GlobalConfig.ACCESS + ossUrl);
}
}
Postman模拟文件上传。"key":"Content-Type","value":"multipart/form-data"
上传成功,返回了文件OSS的地址。
OSS控制台查看,文件已经上传成功。
4.下载文件
根据上传成功返回的ossUrl地址进行文件下载。注意:前面访问的access: http://tianhong-bucket.oss-cn-hangzhou.aliyuncs.com/不用传入。只需后面的tianhong-bucket/2020-07-03/12e7b00c21e14ebf9bf5b16a427359e6-655c82-timg.jpg具体文件路径即可。
@GetMapping("/downLoad")
public void downloadByUrl(HttpServletRequest request, String ossUrl, HttpServletResponse response) throws Exception {
if (null != ossUrl) {
String fileTitle = ossUrl.substring(ossUrl.lastIndexOf("/") + 1, ossUrl.length());
fileTitle = fileTitle.substring(fileTitle.indexOf("-")+1,fileTitle.length());
String fileTitleDownName = ossUrl.substring(ossUrl.lastIndexOf("-") + 1, ossUrl.length());
//从oss读取文件
OSSClient ossClient = new OSSClient(GlobalConfig.ENDPOINT, GlobalConfig.ACCESS_KEY_ID, GlobalConfig.ACCESS_KEY_SECRET);
// 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
ossClient.getObject(new GetObjectRequest(GlobalConfig.BUCKET_NAME,ossUrl),new File(downLoadPath+fileTitleDownName));
//临时文件下载
File file = new File(GlobalConfig.UPLOAD_PATH + fileTitle);
FileInputStream stream = new FileInputStream(file);
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
String name = null;
String agent = request.getHeader("User-Agent").toLowerCase();
if (agent.contains("msie") || agent.contains("like gecko")) {
// win10 ie edge 浏览器 和其他系统的ie
name = URLEncoder.encode(fileTitleDownName, "UTF-8");
} else {
// fe
name = new String(fileTitleDownName.getBytes("UTF-8"), "iso-8859-1");
}
response.setHeader("Content-Disposition", "attachment; filename=" + name);
OutputStream os = response.getOutputStream();
byte[] b = new byte[2048];
int length;
while ((length = stream.read(b)) > 0) {
os.write(b, 0, length);
}
//关掉输出流,否则文件无法删除
stream.close();
os.flush();
os.close();
//删除上传时 保存在F盘的源文件
file.delete();
}
}
下载成功。