SpringBoot整合OSS文件服务器(文件上传、下载及在线地址)
时间:2024-01-05 05:07:01
pom引入依赖包
<!--阿里云oss--> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.8.0</version> </dependency>
阿里云OSS配置(yml)
#阿里云oss aliyun: endpoint: http://oss-cn-beijing.aliyuncs.com # oss访问域名的外部服务 access-key-id: *****njArc******3s # 用户标识用于访问身份验证 access-key-secret: *******WB9**** # 用户用于加密签名字符串和oss密钥用于验证签名字符串 bucket: *** #桶名(文件目录) dir:
工具类,复制即用
/** * 阿里云-OSS文件类 */ @Slf4j @Configuration @PropertySource("classpath:/application.yml") @Component public class AliOssCloudUtil {
@Value("${aliyun.endpoint:#{null}}") private String endpoint; @Value("${aliyun.access-key-id:#{null}}") private String accessKeyId; @Value("${aliyun.access-key-secret:#{null}}") private String accessKeySecret; @Value("${aliyun.bucket:#{null}}")
private String bucketName;
@Value("${aliyun.dir:#{null}}")
private String dir;
public String getDir() {
return dir;
}
/** * 获取OSS * @return */
public OSS getOSSClient(){
return new OSSClientBuilder().build(endpoint,accessKeyId,accessKeySecret);
}
/** * 上传到OSS服务器 * * @param instream 文件流 * @param fileName 文件名称 包括后缀名 * @return 出错返回"" ,唯一MD5数字签名 */
public String uploadFile2OSS(InputStream instream, String fileName) {
OSS ossClient = getOSSClient();
String ret = "";
// 判断bucket是否已经存在,不存在进行创建
if (!doesBucketExist(ossClient)) {
createBucket(ossClient);
}
try {
//创建上传Object的Metadata
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(instream.available());
objectMetadata.setCacheControl("no-cache");
objectMetadata.setHeader("Pragma", "no-cache");
objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
objectMetadata.setContentDisposition("inline;filename=" + fileName);
// 指定上传文件操作时是否覆盖同名Object。
// 不指定x-oss-forbid-overwrite时,默认覆盖同名Object。
// 指定x-oss-forbid-overwrite为false时,表示允许覆盖同名Object。
// 指定x-oss-forbid-overwrite为true时,表示禁止覆盖同名Object,如果同名Object已存在,程序将报错。
objectMetadata.setHeader("x-oss-forbid-overwrite", "false");
String objectName = dir + fileName;
//上传文件
ossClient.putObject(bucketName, objectName, instream, objectMetadata);
// 设置URL过期时间(7天)
Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000 * 24 * 7);
URL url = ossClient.generatePresignedUrl(bucketName, objectName,expiration);
log.info(objectName);
ret = url.toString().split("\\?")[0];
} catch (IOException e) {
e.printStackTrace();
} finally {
ossClient.shutdown();
try {
if (instream != null) {
instream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
/** * 获取文件在线地址 * @param objectName 文件路径 filePath * @param expiration 过期时间 * @return 返回文件在线路径 */
public String getOnlineAddress(String objectName,Date expiration){
OSS ossClient = getOSSClient();
String ret = null;
try {
URL url = ossClient.generatePresignedUrl(bucketName, objectName,expiration);
ret = url.toString().split("\\?")[0];
} catch (ClientException e) {
e.printStackTrace();
}finally {
ossClient.shutdown();
}
return ret;
}
/** * 判断文件是否存在。doesObjectExist还有一个参数isOnlyInOSS, * 如果为true则忽略302重定向或镜像;如果为false,则考虑302重定向或镜像。 * yourObjectName 表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 * * @return 存在返回true */
public boolean doesObjectExist(OSS ossClient,String objectName) {
boolean exists = ossClient.doesObjectExist(bucketName, dir + objectName);
return exists;
}
/** * 判断Bucket是否存在 * * @return 存在返回true */
public boolean doesBucketExist(OSS ossClient) {
boolean exists = ossClient.doesBucketExist(bucketName);
return exists;
}
/** * 创建Bucket */
public void createBucket(OSS ossClient) {
CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
// 设置bucket权限为公共读,默认是私有读写
createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
// 设置bucket存储类型为低频访问类型,默认是标准类型
createBucketRequest.setStorageClass(StorageClass.IA);
boolean exists = ossClient.doesBucketExist(bucketName);
if (!exists) {
try {
ossClient.createBucket(createBucketRequest);
// 关闭client
// ossClient.shutdown();
} catch (Exception e) {
log.error(e.getMessage());
}
}
}
/** * 判断OSS服务文件上传时文件的contentType * @param FilenameExtension 文件后缀 * @return String */
public static String getcontentType(String FilenameExtension) {
if ("bmp".equalsIgnoreCase(FilenameExtension)) {
return "image/bmp";
}
if ("gif".equalsIgnoreCase(FilenameExtension)) {
return "image/gif";
}
if ("jpeg".equalsIgnoreCase(FilenameExtension) ||
"jpg".equalsIgnoreCase(FilenameExtension) ||
"png".equalsIgnoreCase(FilenameExtension)) {
return "image/jpeg";
}
if ("html".equalsIgnoreCase(FilenameExtension)) {
return "text/html";
}
if ("txt".equalsIgnoreCase(FilenameExtension)) {
return "text/plain";
}
if ("vsd".equalsIgnoreCase(FilenameExtension)) {
return "application/vnd.visio";
}
if ("pptx".equalsIgnoreCase(FilenameExtension) ||
"ppt".equalsIgnoreCase(FilenameExtension)) {
return "application/vnd.ms-powerpoint";
}
if ("docx".equalsIgnoreCase(FilenameExtension) ||
"doc".equalsIgnoreCase(FilenameExtension)) {
return "application/msword";
}
if ("xml".equalsIgnoreCase(FilenameExtension)) {
return "text/xml";
}
return "image/jpeg";
}
/** * 通过文件名下载文件 * * @param objectName 要下载的文件名 * @param localFileName 本地要创建的文件名 */
public void downloadFile(HttpServletResponse response, String objectName, String localFileName){
// 创建OSSClient实例。
OSS ossClient = getOSSClient();
try {
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
OSSObject ossObject = ossClient.getObject(bucketName, objectName);
// 读去Object内容 返回
BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
//通知浏览器以附件形式下载
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName, "utf-8"));
//BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(new File("f:\\a.txt")));
byte[] car = new byte[1024];
int L = 0;
while ((L = in.read(car)) != -1) {
out.write(car, 0, L);
}
if (out != null) {
out.flush();
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭OSSClient。
ossClient.shutdown();
}
}
/** * 批量下载为zip * @param response * @param fileName oss文件路径集合 * @param fileName 下载出来的zip文件名(一般以合同名命名) 如:测试合同,zip */
public void downForZip( HttpServletResponse response,List<String> filePath,String fileName){
// 创建临时文件
File zipFile = null;
try {
zipFile = File.createTempFile("test", ".zip");
FileOutputStream f = new FileOutputStream(zipFile);
/** * 作用是为任何OutputStream产生校验和 * 第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种) */
CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());
// 用于将数据压缩成Zip文件格式
ZipOutputStream zos = new ZipOutputStream(csum);
OSS ossClient= getOSSClient();
for (String ossFile : filePath) {
// 获取Object,返回结果为OSSObject对象
OSSObject ossObject = ossClient.getObject(bucketName, ossFile);
// 读去Object内容 返回
InputStream inputStream = ossObject.getObjectContent();
// 对于每一个要被存放到压缩包的文件,都必须调用ZipOutputStream对象的putNextEntry()方法,确保压缩包里面文件不同名
String name=ossFile.substring(ossFile.lastIndexOf("/")+1);
zos.putNextEntry(new ZipEntry(name));
int bytesRead = 0;
// 向压缩文件中输出数据
while ((bytesRead = inputStream.read()) != -1) {
zos.write(bytesRead);
}
inputStream.close();
zos.closeEntry(); // 当前文件写完,定位为写入下一条项目
}
zos.close();
response.reset();
response.setContentType("text/plain");
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Location", fileName);
response.setHeader("Cache-Control", "max-age=0");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
FileInputStream fis = new FileInputStream(zipFile);
BufferedInputStream buff = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
byte[] car = new byte[1024];
int l = 0;
while (l < zipFile.length()) {
int j = buff.read(car, 0, 1024);
l += j;
out.write(car, 0, j);
}
// 关闭流
fis.close();
buff.close();
out.close();
ossClient.shutdown();
// 删除临时文件
zipFile.delete();
} catch (IOException e1) {
e1.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
}
}