阿里云oss的使用
oss云存储:Object Storage Service对象存储。您需要先创建Bucket,并指定Bucket的地域、访问权限、存储类型等属性。创建Bucket后,您可以将数据以Object的形式上传到Bucket,并指定Object的文件名(Key)作为其唯一标识。
引入依赖
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.10.2</version>
</dependency>
oss上传下载工具类
/**
* @desc oss文件上传下载工具类
*/
@Component
class OssUtil {
@Value("\${aliyun.oss.endpoint}")
private val endpoint: String? = null//外网访问 地域节点
@Value("\${aliyun.oss.accessKeyId}")
private val keyId: String? = null
@Value("\${aliyun.oss.accessKeySecret}")
private val keySecret: String? = null
@Value("\${aliyun.oss.bucketName}")
private val bucketName: String? = null
/**
* @desc 文件上传
*/
fun upload(file: MultipartFile): FileInfo {
var ossClient: OSS? = null
val fileInfo = FileInfo("", "")
try {
// 创建OSSClient实例。
ossClient = OSSClientBuilder().build(endpoint, keyId, keySecret)
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流。
val fileInputStream = file.inputStream
// 获取上传文件的全称
val filename = file.originalFilename
// 获取UUID
val uuid = UUID.randomUUID().toString().replace("-".toRegex(), "")
// 获取上传文件的后缀名(文件类型)
val fileType = filename.substring(filename.lastIndexOf("."))
// 拼接文件名字(文件名为id+类型)
val newFileName = uuid + fileType
// 如果要实现文件的浏览效果,一定要设置权限
// 1.设置文件的ACL权限:公共读 or 公共读写
// 2.设置文本类型(jpg/png/html/txt/...)
val objectMetadata = ObjectMetadata()
// 设置公共读权限
objectMetadata.setObjectAcl(CannedAccessControlList.PublicRead)
// 设置文件类型ContentType
objectMetadata.contentType = getContentType(fileType)
// 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
ossClient.putObject(bucketName, newFileName, fileInputStream, objectMetadata)
//返回的文件信息赋值
fileInfo.fileName = filename
fileInfo.fileId = uuid
} catch (e: Exception) {
e.printStackTrace()
} finally {
ossClient!!.shutdown()
}
return fileInfo
}
/**
* @desc 文件下载
*/
fun download(fileId: String, fileName: String, response: HttpServletResponse) {
//根据id和类型找文件
val fileType = fileName.substring(fileName.lastIndexOf("."))
val filename = fileId + fileType
var bufferedInputStream: BufferedInputStream? = null
var outputStream: OutputStream? = null
try {
response.reset()
response.characterEncoding = "utf-8"
response.contentType = "application/x-msdownload"
response.addHeader(
"Content-Disposition",
"attachment;filename=" + String(filename.toByteArray(charset("UTF-8")))
)
// 创建OSSClient实例。
val ossClient = OSSClientBuilder().build(endpoint, keyId, keySecret)
//public OSSObject getObject(String bucketName, String key) throws OSSException, ClientException;
// key值为 不包含Bucket名称在内的Object完整路径,例如2021/11/04/129904d9-d959-44e1-bcaa-5f7a0b663287.txt。
val `object` = ossClient.getObject(bucketName, filename)
bufferedInputStream = BufferedInputStream(`object`.objectContent)
outputStream = response.outputStream
val bytes = ByteArray(1024)
var len :Int
while (bufferedInputStream.read(bytes).also { len = it } != -1) {
outputStream.write(bytes, 0, len)
}
outputStream.flush()
ossClient.shutdown()
} catch (e: IOException) {
e.printStackTrace()
} finally {
try {
outputStream?.close()
bufferedInputStream?.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
companion object {
/**
* Description: 判断OSS服务文件上传时文件的contentType
*
* @param FilenameExtension 文件后缀
* @return String
*/
fun getContentType(FilenameExtension: String): String {
if (FilenameExtension.equals(".bmp", ignoreCase = true)) {
return "image/bmp"
}
if (FilenameExtension.equals(".gif", ignoreCase = true)) {
return "image/gif"
}
if (FilenameExtension.equals(".jpeg", ignoreCase = true) ||
FilenameExtension.equals(".jpg", ignoreCase = true) ||
FilenameExtension.equals(".png", ignoreCase = true)
) {
return "image/jpg"
}
if (FilenameExtension.equals(".html", ignoreCase = true)) {
return "text/html"
}
if (FilenameExtension.equals(".txt", ignoreCase = true)) {
return "text/plain"
}
if (FilenameExtension.equals(".vsd", ignoreCase = true)) {
return "application/vnd.visio"
}
if (FilenameExtension.equals(".pptx", ignoreCase = true) ||
FilenameExtension.equals(".ppt", ignoreCase = true)
) {
return "application/vnd.ms-powerpoint"
}
if (FilenameExtension.equals(".docx", ignoreCase = true) ||
FilenameExtension.equals(".doc", ignoreCase = true)
) {
return "application/msword"
}
return if (FilenameExtension.equals(".xml", ignoreCase = true)) {
"text/xml"
} else "image/jpg"
}
}
}
yml配置(oss的地域,key,secret,桶名称)
minio云存储的使用
minio云存储:开源的,基于Go语言发开的高性能、分布式的对象存储系统
引入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.0.3</version>
</dependency>
minio上传下载工具类
@Component
class MinioTools {
@Value("\${minio.endpoint}")
private val minioUrl: String? = null
@Value("\${minio.MINIO_ROOT_USER}")
private val minioUserName: String? = null
@Value("\${minio.MINIO_ROOT_PASSWORD}")
private val minioPassWord: String? = null
private var minioClient: MinioClient? = null
/**
* 文件上传
* @param fileList web上传文件接收的参数
* @param path 文件路径
* @return
*/
fun uploadFile(fileList: List<MultipartFile>, path: String): List<Shpwxkz> {
minioClient = MinioClient(minioUrl, minioUserName, minioPassWord)
val result: MutableList<Shpwxkz> = ArrayList<Shpwxkz>()
var filesManage: Shpwxkz
for (file in fileList) {
filesManage = Shpwxkz()
// 检查存储桶是否已经存在 path必须小写
val id = UUID.randomUUID().toString()
val fileName: String = file.originalFilename as String
val tempNames = path.split("/".toRegex(), limit = 2).toTypedArray()
val bucketName = tempNames[1]
var objectName: String = if (tempNames.size > 1) {
"$id$fileName"
} else {
id + fileName
}
val isExist: Boolean = minioClient!!.bucketExists(bucketName)
if (isExist) {
println("Bucket already exists.")
} else {
// 创建一个新的存储桶用于存储文件
minioClient!!.makeBucket(path)
}
val `in`: InputStream? = file?.inputStream
if (`in` != null) {
minioClient!!.putObject(bucketName, objectName, `in`, PutObjectOptions(`in`.available().toLong(), -1))
}
filesManage.id = id
filesManage.wjlj = path
filesManage.bgmc = fileName
result.add(filesManage)
}
return result
}
/**
* 文件上传
* @param file web上传文件接收的参数
* @param path 文件路径
* @return
*/
fun uploadSingleFile(file: MultipartFile, path: String): Shpwxkz {
minioClient = MinioClient(minioUrl, minioUserName, minioPassWord)
var result: Shpwxkz = Shpwxkz()
val filesManage = Shpwxkz()
// 检查存储桶是否已经存在 path必须小写
val id = UUID.randomUUID().toString()
val fileName: String = file.originalFilename as String
val tempNames = path.split("/".toRegex(), limit = 2).toTypedArray()
val bucketName = tempNames[1]
val objectName: String = if (tempNames.size > 1) {
"$id$fileName"
} else {
id + fileName
}
val isExist: Boolean = minioClient!!.bucketExists(bucketName)
if (isExist) {
println("Bucket already exists.")
} else {
// 创建一个新的存储桶用于存储文件
minioClient!!.makeBucket(path)
}
val `in`: InputStream = file.inputStream
minioClient!!.putObject(bucketName, objectName, `in`, PutObjectOptions(`in`.available().toLong(), -1))
result.id = id
result.wjlj = path
result.bgmc = fileName
return result
}
@Throws(IOException::class)
fun getStreamDownloadFile(fileName: String, id: String, path: String, response: HttpServletResponse) {
var out: ServletOutputStream? = null
var `in`: InputStream? = null
try {
val expires = 60 * 60 * 24
minioClient = MinioClient(minioUrl, minioUserName, minioPassWord)
val tempNames = path.split("/".toRegex(), limit = 2).toTypedArray()
val bucketName = tempNames[1]
val objectName: String = if (tempNames.size > 1) {
"$id$fileName"
} else {
fileName
}
var address = minioClient!!.presignedGetObject(bucketName, objectName, expires)
val url = URL(address)
val connection = url.openConnection()
if (address.contains("%")) {
address = try {
URLDecoder.decode(address, "UTF-8")
} catch (e: UnsupportedEncodingException) {
throw e
}
}
`in` = connection.getInputStream()
// 设置响应类型为html,编码为utf-8,处理相应页面文本显示的乱码
response.contentType = "application/octet-stream"
// 设置文件头:最后一个参数是设置下载文件名
response.setHeader(
"Content-disposition",
"attachment;fileName*=UTF-8''" + UriUtils.encode(fileName, "UTF-8")
)
out = response.outputStream
// 读取文件流
var len = 0
val buffer = ByteArray(1024 * 10)
while (`in`.read(buffer).also { len = it } != -1) {
out.write(buffer, 0, len)
}
out.flush()
} catch (e: Exception) {
e.printStackTrace()
} finally {
response.flushBuffer()
try {
out!!.close()
`in`!!.close()
} catch (e: NullPointerException) {
throw e
} catch (e: Exception) {
throw e
}
}
}
}