文件上传下载接口[阿里云OSS,minio,本地]
< 返回列表时间: 2020-06-17来源:OSCHINA
1.定义客户端接口 public interface ApiClient { VirtualFile upload(MultipartFile file); VirtualFile upload(File file); VirtualFile upload(InputStream is, String fileName); boolean removeFile(String key); byte[] download(String fileName); }
2.定义实现接口父类客户端 public abstract class BaseApiClient implements ApiClient { /** * 存储类型 */ protected String storageType; /** * 文件名称 */ protected String objectName; /** * 后缀 */ protected String suffix; /** * 默认文件大小 5M */ private static final long DEFAULT_MAX_SIZE = 5 * 1024 * 1024; public BaseApiClient() { } public BaseApiClient(String storageType) { this.storageType = storageType; } @Override public VirtualFile upload(MultipartFile file) { this.assertClient(); if (file == null) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:文件不可为空"); } this.assertSize(file.getSize()); try { VirtualFile virtualFile = this.upload(file.getInputStream(), file.getOriginalFilename()); virtualFile.setSize(file.getSize()); return virtualFile; } catch (IOException e) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:" + e.getMessage()); } } @Override public VirtualFile upload(File file) { this.assertClient(); if (file == null) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:文件不可为空"); } this.assertSize(file.length()); try { VirtualFile virtualFile = this.upload(new FileInputStream(file), file.getName()); virtualFile.setSize(file.length()); return virtualFile; } catch (FileNotFoundException ex) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:" + ex.getMessage()); } } @Override public abstract VirtualFile upload(InputStream is, String fileName); @Override public abstract boolean removeFile(String fileName); protected abstract void assertClient(); /** * 生成key * * @param prefix * @param fileName */ public void createOjectName(String dir, String fileName) { this.suffix = FileUtils.getSuffix(fileName); if (!FileUtils.allAssertSuffix(this.suffix, MimeTypeConstants.DEFAULT_ALLOWED_EXTENSION)) { throw new RuntimeException("[" + this.storageType + "] 非法的文件[" + fileName + "]!目前只支持以下格式:" + Arrays.toString(MimeTypeConstants.DEFAULT_ALLOWED_EXTENSION)); } this.objectName = getPathFileName(dir, fileName); } public String getPathFileName(String dir, String fileName) { fileName = fileName.replace("_", " "); String temporary = DateUtil.format(new Date(), "yyyyMMdd") + "/" + SecureUtil.md5(fileName + System.nanoTime()); return dir + (temporary + "." + this.suffix); } /** * 文件大小校验 * * @param allExtension * @throws IOException */ public void assertSize(long size) { if (DEFAULT_MAX_SIZE != -1 && DEFAULT_MAX_SIZE < size) { throw new RuntimeException( "[" + this.storageType + "]允许的文件最大大小是" + (DEFAULT_MAX_SIZE / 1024 / 1024) + "MB!"); } } }
3.定义阿里云OSS客户端实现 public class AliyunApiClient extends BaseApiClient { private static final String STORAGE_CLIENT = "阿里云OSS"; private static final String ENDPOINT = "YOUR ENDPOINT"; private static final String ACCESSKEYID = "YOUR ACCESSKEYID"; private static final String ACCESSKEYSECRET = "YOUR ACCESSKEYSECRET"; private static final String BUCKETNAME = "YOUR BUCKETNAME"; private static final String BUCKETURL = "YOUR BUCKETURL"; /** * 默认上传目录 */ private static final String DEFAULT_DIR = "upload/"; private AliyunOSSApi ossApi; public AliyunApiClient() { super(STORAGE_CLIENT); ossApi = new AliyunOSSApi(ENDPOINT, ACCESSKEYID, ACCESSKEYSECRET); } @Override public VirtualFile upload(InputStream is, String fileName) { this.assertClient(); this.createOjectName(DEFAULT_DIR, fileName); try { ossApi.uploadFile(BUCKETNAME, this.objectName, is); VirtualFile virtualFile = new VirtualFile(); virtualFile.setSuffix(this.suffix); virtualFile.setFilePath(this.objectName); virtualFile.setFullFilePath(BUCKETURL + this.objectName); virtualFile.setOriginalFileName(fileName); virtualFile.setUploadTime(new Date()); virtualFile.setClient(STORAGE_CLIENT); return virtualFile; } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:" + e.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public boolean removeFile(String fileName) { this.assertClient(); if (StringUtils.isEmpty(fileName)) { throw new RuntimeException("[" + this.storageType + "]删除文件失败:文件key为空"); } try { ossApi.deleteFile(BUCKETNAME, fileName); return true; } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]删除文件失败:" + e.getMessage()); } } @Override public byte[] download(String objectName) { this.assertClient(); if (StringUtils.isEmpty(objectName)) { throw new RuntimeException("[" + this.storageType + "]下载文件失败:文件key为空"); } try { return ossApi.download(BUCKETNAME, objectName); } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]下载文件失败:" + e.getMessage()); } } /** * 客户端配置校验 */ @Override public void assertClient() { if (null == ossApi) { throw new RuntimeException("[" + this.storageType + "]尚未配置阿里云OSS,文件上传功能暂时不可用!"); } } }
连接阿里云OSS客户端 public class AliyunOSSApi { private OSSClient client; public AliyunOSSApi(OSSClient oss) { this.client = oss; } public AliyunOSSApi(String endpoint, String accessKeyId, String accessKeySecret) { // 创建ClientConfiguration实例,按照您的需要修改默认参数。 // ClientBuilderConfiguration conf = new ClientBuilderConfiguration(); // 开启支持CNAME。CNAME是指将自定义域名绑定到存储空间上。 // conf.setSupportCname(true); client = new OSSClient(endpoint, accessKeyId, accessKeySecret); } /** * 创建存储空间 * * @param bucketName 存储空间名称 */ public boolean createBucket(String bucketName) { try { boolean exists = this.client.doesBucketExist(bucketName); if (exists) { throw new RuntimeException("[阿里云OSS] Bucket创建失败!Bucket名称[" + bucketName + "]已被使用!"); } // 创建CreateBucketRequest对象 CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); // 设置bucket权限为公共读,默认是私有读写 createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead); // 此处以设置存储空间的存储类型为标准存储为例。 createBucketRequest.setStorageClass(StorageClass.Standard); // 创建存储空间。 this.client.createBucket(createBucketRequest); return true; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 列举存储空间 * * @return */ public List<Bucket> listBuckets() { try { return this.client.listBuckets(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 获取存储空间的信息 * * @param bucketName 存储空间名称 * @return */ public BucketInfo getBucketInfo(String bucketName) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("获取[阿里云OSS] 获取存储空间的信息失败!Bucket名称[" + bucketName + "]不存在!"); } BucketInfo info = client.getBucketInfo(bucketName); return info; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 设置存储空间的访问权限 * * @param bucketName 存储空间名称 * @param controlList 存储空间的访问权限 * @return */ public boolean setBucketAcl(String bucketName, CannedAccessControlList controlList) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("设置[阿里云OSS]设置存储空间的访问权限!Bucket名称[" + bucketName + "]不存在!"); } client.setBucketAcl(bucketName, controlList); return true; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 获取存储空间访问权限 * * @param bucketName 存储空间名称 */ public AccessControlList getBucketAcl(String bucketName) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("获取[阿里云OSS]存储空间访问权限!Bucket名称[" + bucketName + "]不存在!"); } AccessControlList acl = client.getBucketAcl(bucketName); return acl; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 设置防盗链 * * @param bucketName 存储空间名称 * @param RefererList 允许指定的域名访问OSS资源 */ public boolean setBucketReferer(String bucketName, List<String> RefererList) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法设置Referer白名单!Bucket不存在:" + bucketName); } if (CollectionUtils.isEmpty(RefererList)) { return false; } // 设置存储空间Referer列表。设为true表示Referer字段允许为空 BucketReferer br = new BucketReferer(true, RefererList); this.client.setBucketReferer(bucketName, br); return true; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 获取防盗链信息 * * @param bucketName 存储空间名 */ public List<String> getReferers(String bucketName) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法清空Referer白名单!Bucket不存在:" + bucketName); } BucketReferer br = this.client.getBucketReferer(bucketName); return br.getRefererList(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 清空防盗链信息 * * @param bucketName 存储空间名 */ public boolean removeReferers(String bucketName) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法清空Referer白名单!Bucket不存在:" + bucketName); } // 默认允许referer字段为空,且referer白名单为空。 BucketReferer br = new BucketReferer(); client.setBucketReferer(bucketName, br); return true; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 授权访问 * * @param bucketName * @param objectName * @param expiration 失效时长 * @param style 图片样式 * @return */ public String generatePresignedUrl(String bucketName, String objectName, Date expiration, String style) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法进行URL临时授权!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, objectName)) { throw new RuntimeException("[阿里云OSS] 无法进行URL临时授权!文件不存在:" + bucketName + "/" + objectName); } if (null == expiration) { // 设置URL过期时间为1小时 expiration = new Date(new Date().getTime() + 1000 * 60 * 10); } GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET); req.setExpiration(expiration); req.setProcess(style); // 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。 URL url = client.generatePresignedUrl(req); return url.toString(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } public String uploadFile(String bucketName, String objectName, String filePath) { return uploadFile(bucketName, objectName, new File(filePath)); } /** * 文件上传 * * @param file 待上传的文件 * @param ObjectName 文件名:最终保存到云端的文件名 * @param bucketName 需要上传到的目标bucket */ public String uploadFile(String bucketName, String objectName, File file) { try { PutObjectResult result = client.putObject(bucketName, objectName, file); return result.getETag(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 文件上传 * * @param inputStream 待上传的文件流 * @param ObjectName 文件名:最终保存到云端的文件名 * @param bucketName 需要上传到的目标bucket */ public String uploadFile(String bucketName, String objectName, InputStream inputStream) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法上传文件!Bucket不存在:" + bucketName); } PutObjectResult result = this.client.putObject(bucketName, objectName, inputStream); return result.getETag(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 流式下载 * * @param inputStream 待上传的文件流 * @param bucketName 需要上传到的目标bucket * @param objectName 需要下到的目标bucket */ public byte[] download(String bucketName, String ObjectName) throws IOException { BufferedInputStream in = null; ByteArrayOutputStream out = null; try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, ObjectName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!文件不存在:" + bucketName + "/" + ObjectName); } OSSObject ossObject = client.getObject(bucketName, ObjectName); // 流下载,一次处理部分内容,需要添加缓存区式 in = new BufferedInputStream(ossObject.getObjectContent()); out = new ByteArrayOutputStream(); byte[] bs = new byte[1024]; int n; while ((n = in.read(bs)) != -1) { out.write(bs, 0, n); } return out.toByteArray(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (null != out) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != in) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (this.client != null) { this.client.shutdown(); } } return null; } /** * 下载到本地文件 * * @param inputStream 待上传的文件流 * @param bucketName 需要上传到的目标bucket * @param localPath 本地路径 * @return */ public ObjectMetadata dowload(String bucketName, String objectName, String localPath) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, objectName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!文件不存在:" + bucketName + "/" + objectName); } File file = new File(localPath + objectName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。 ObjectMetadata metadata = this.client.getObject(new GetObjectRequest(bucketName, objectName), file); return metadata; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 下载到本地文件 * * @param inputStream 待上传的文件流 * @param bucketName 需要上传到的目标bucket * @param style 图片样式 * @param localPath 本地路径 * @return */ public ObjectMetadata dowloadImage(String bucketName, String objectName, String style, String localPath) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!Bucket不存在:" + bucketName); } if (!FileUtils.allAssertSuffix(FileUtils.getSuffix(objectName), MimeTypeConstants.IMAGE_ALLOWED_EXTENSION)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!不支持此图像格式:" + objectName); } if (!this.client.doesObjectExist(bucketName, objectName)) { throw new RuntimeException("[阿里云OSS] 无法下载文件!文件不存在:" + bucketName + "/" + objectName); } File file = new File(localPath + objectName); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } GetObjectRequest request = new GetObjectRequest(bucketName, objectName); request.setProcess(style); // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。 ObjectMetadata metadata = this.client.getObject(request, file); return metadata; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 判断文件是否存在 * * @param ObjectName OSS中保存的文件名 * @param bucketName 存储空间 */ public boolean isExistFile(String bucketName, String objectName) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] Bucket不存在:" + bucketName); } return this.client.doesObjectExist(bucketName, objectName); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 列举文件 */ public List<OSSObjectSummary> getOSSObjectSummary(String bucketName) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] Bucket不存在:" + bucketName); } ObjectListing objectListing = client.listObjects(bucketName); return objectListing.getObjectSummaries(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 修改指定bucket下的文件的访问权限 * * @param ObjectName OSS中保存的文件名 * @param bucketName 保存文件的目标bucket * @param acl 权限 */ public void setFileAcl(String bucketName, String ObjectName, CannedAccessControlList acl) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("[阿里云OSS] 无法修改文件的访问权限!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, ObjectName)) { throw new RuntimeException("[阿里云OSS] 无法修改文件的访问权限!文件不存在:" + bucketName + "/" + ObjectName); } this.client.setObjectAcl(bucketName, ObjectName, acl); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } } /** * 获取指定bucket下的文件的访问权限 * * @param ObjectName OSS中保存的文件名 * @param bucketName 存储空间 * @return */ public ObjectPermission getFileAcl(String bucketName, String ObjectName) { try { if (!this.client.doesBucketExist(bucketName)) { throw new RuntimeException("[阿里云OSS] 无法获取文件的访问权限!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, ObjectName)) { throw new RuntimeException("[阿里云OSS] 无法获取文件的访问权限!文件不存在:" + bucketName + "/" + ObjectName); } return this.client.getObjectAcl(bucketName, ObjectName).getPermission(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } /** * 删除单文件 * * @param bucketName 保存文件的目标bucket * @param ObjectName OSS中保存的文件名 */ public boolean deleteFile(String bucketName, String ObjectName) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("[阿里云OSS] 文件删除失败!Bucket不存在:" + bucketName); } if (!this.client.doesObjectExist(bucketName, ObjectName)) { throw new RuntimeException("[阿里云OSS] 文件删除失败!文件不存在:" + bucketName + "/" + ObjectName); } this.client.deleteObject(bucketName, ObjectName); return true; } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return false; } /** * 删除多文件 * * @param bucketName 保存文件的目标bucket * @param ObjectName OSS中保存的文件名 */ public List<String> deleteFile(String bucketName, List<String> keys) { try { boolean exists = this.client.doesBucketExist(bucketName); if (!exists) { throw new RuntimeException("[阿里云OSS] 文件删除失败!Bucket不存在:" + bucketName); } for (String ObjectName : keys) { if (!this.client.doesObjectExist(bucketName, ObjectName)) { throw new RuntimeException("[阿里云OSS] 文件删除失败!文件不存在:" + bucketName + "/" + ObjectName); } } DeleteObjectsResult deleteObjectsResult = this.client .deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys)); return deleteObjectsResult.getDeletedObjects(); } catch (OSSException oe) { oe.printStackTrace(); } catch (ClientException ce) { ce.printStackTrace(); } finally { if (this.client != null) { this.client.shutdown(); } } return null; } }
3.定义本地客户端实现 public class LocalApiClient extends BaseApiClient { private static final String STORAGE_CLIENT = "local"; private static final String URL = Constants.WEB_PATH; /** * 默认上传目录 */ private static final String DEFAULT_DIR = "upload/"; public LocalApiClient() { super(STORAGE_CLIENT); } @Override public VirtualFile upload(InputStream is, String fileName) { this.assertClient(); this.createOjectName(DEFAULT_DIR, fileName); File realFilePath = FileUtils.getAbsoluteFile(URL, this.objectName); try (FileOutputStream out = new FileOutputStream(realFilePath)) { FileCopyUtils.copy(is, out); VirtualFile virtualFile = new VirtualFile(); virtualFile.setSuffix(this.suffix); virtualFile.setFilePath(this.objectName); virtualFile.setFullFilePath(URL + this.objectName); virtualFile.setOriginalFileName(fileName); virtualFile.setUploadTime(new Date()); virtualFile.setClient(STORAGE_CLIENT); return virtualFile; } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]文件上传失败:" + e.getMessage()); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public boolean removeFile(String fileName) { this.assertClient(); if (StringUtils.isEmpty(fileName)) { throw new RuntimeException("[" + this.storageType + "]删除文件失败:文件key为空"); } File file = new File(URL + fileName); if (!file.exists()) { throw new RuntimeException("[" + this.storageType + "]删除文件失败:文件不存在[" + URL + fileName + "]"); } try { return file.delete(); } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]删除文件失败:" + e.getMessage()); } } @Override public byte[] download(String fileName) { this.assertClient(); if (StringUtils.isEmpty(fileName)) { throw new RuntimeException("[" + this.storageType + "]下载文件失败:文件key为空"); } try { InputStream stream = new FileInputStream(URL + fileName); return IoUtil.readBytes(stream); } catch (Exception e) { throw new RuntimeException("[" + this.storageType + "]下载文件失败:" + e.getMessage()); } } @Override protected void assertClient() { if (StringUtils.isEmpty(URL) || StringUtils.isEmpty(DEFAULT_DIR)) { throw new RuntimeException("[" + this.storageType + "]尚未配置,文件上传功能暂时不可用!"); } } }
选择需要连接的客户端 public class ConnectClient { public ApiClient getClient() { // 实际查询数据库配置 String storage = "aliyun"; if (StringUtils.isEmpty(storage)) { throw new RuntimeException("[文件服务]当前系统暂未配置文件服务相关的内容!"); } ApiClient client = null; switch (storage) { case "local": client = new LocalApiClient(); break; case "aliyun": client = new AliyunApiClient(); break; default: break; } if (null == client) { throw new RuntimeException("[文件服务]当前系统暂未配置文件服务相关的内容!"); } return client; } }
编写上传接口 public interface FileUpload { /** * 上传文件 * * @param file 待上传的文件流 */ VirtualFile upload(InputStream file,String fileName); /** * 上传文件 * * @param file 待上传的文件 */ VirtualFile upload(File file); /** * 上传文件 * * @param file 待上传的文件 */ VirtualFile upload(MultipartFile file); /** * 删除文件 * * @param filePath 文件路径 */ boolean delete(String filePath); }
连接客户端,实现上传接口 public class GlobalFileUpload extends ConnectClient implements FileUpload { @Override public VirtualFile upload(InputStream is, String fileName) { ApiClient client = this.getClient(); return client.upload(is, fileName); } @Override public VirtualFile upload(File file) { ApiClient client = this.getClient(); return client.upload(file); } @Override public VirtualFile upload(MultipartFile file) { ApiClient client = this.getClient(); return client.upload(file); } @Override public boolean delete(String filePath) { if (StringUtils.isEmpty(filePath)) { throw new RuntimeException("[文件服务]文件删除失败,文件为空!"); } ApiClient apiClient = this.getClient(); return apiClient.removeFile(filePath); } }
编写下载接口 public interface FileDownload { byte[] download(String fileName); }
连接客户端,实现下载接口 public class GlobalFileDownload extends ConnectClient implements FileDownload { @Override public byte[] download(String fileName) { ApiClient client = this.getClient(); return client.download(fileName); } }
文件上传封装 public class FileUploadUtils { public static final List<VirtualFile> upload(List<MultipartFile> files) { List<VirtualFile> virtualFiles = new ArrayList<VirtualFile>(); for (MultipartFile file : files) { virtualFiles.add(upload(file)); } return virtualFiles; } public static final VirtualFile upload(MultipartFile file) { GlobalFileUpload globalFileUpload = new GlobalFileUpload(); return globalFileUpload.upload(file); } public static final VirtualFile upload(InputStream file, String fileName) { GlobalFileUpload globalFileUpload = new GlobalFileUpload(); return globalFileUpload.upload(file, fileName); } public static final VirtualFile upload(File file) { GlobalFileUpload globalFileUpload = new GlobalFileUpload(); return globalFileUpload.upload(file); } public static final boolean delete(String filePath) { GlobalFileUpload globalFileUpload = new GlobalFileUpload(); return globalFileUpload.delete(filePath); } }
文件下载封装 public class FileDownloadUtils { public static void download(HttpServletRequest request, HttpServletResponse response, String filePath, String fileName) { if (StrUtil.isBlank(fileName)) { fileName = StrUtil.subAfter(filePath, "/", true); } response.setCharacterEncoding(CharsetUtil.UTF_8); response.setContentType("multipart/form-data"); OutputStream out = null; try { response.setHeader("Content-Disposition", "attachment;fileName=" + setFileDownloadHeader(request, fileName)); out = response.getOutputStream(); GlobalFileDownload globalFileDownload = new GlobalFileDownload(); out.write(globalFileDownload.download(filePath)); } catch (IOException e) { e.printStackTrace(); } finally { IoUtil.close(out); } } public static void download(String filePath, String fileName) { if (StrUtil.isBlank(fileName)) { fileName = StrUtil.subAfter(filePath, "/", true); } GlobalFileDownload globalFileDownload = new GlobalFileDownload(); try { Filedownload.save(globalFileDownload.download(fileName), "application/octet-stream", URLEncoder.encode(fileName, CharsetUtil.UTF_8)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } /** * 下载文件名重新编码 * * @param request 请求对象 * @param fileName 文件名 * @return 编码后的文件名 */ public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException { final String agent = request.getHeader("USER-AGENT"); String filename = fileName; if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode(filename, CharsetUtil.UTF_8); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 filename = new String(fileName.getBytes(), CharsetUtil.ISO_8859_1); } else if (agent.contains("Chrome")) { // google浏览器 filename = URLEncoder.encode(filename, CharsetUtil.UTF_8); } else { // 其它浏览器 filename = URLEncoder.encode(filename, CharsetUtil.UTF_8); } return filename; } }
返回实体 public class VirtualFile { /** * 文件大小 */ public Long size; /** * 文件后缀(Suffix) */ public String suffix; /** * 文件路径 (不带域名) */ private String filePath; /** * 文件全路径 (带域名) */ private String fullFilePath; /** * 原始文件名 */ private String originalFileName; /** * 业务类型 */ private String bizeType; /** * 业务唯一标识 */ private String bizeId; /** * 上传用户 */ private String uploadUser; /** * 文件上传时间 */ private Date uploadTime; /** * 客户端 */ private String client; public Long getSize() { return size; } public void setSize(Long size) { this.size = size; } public String getSuffix() { return suffix; } public void setSuffix(String suffix) { this.suffix = suffix; } public String getFilePath() { return filePath; } public void setFilePath(String filePath) { this.filePath = filePath; } public String getFullFilePath() { return fullFilePath; } public void setFullFilePath(String fullFilePath) { this.fullFilePath = fullFilePath; } public String getOriginalFileName() { return originalFileName; } public void setOriginalFileName(String originalFileName) { this.originalFileName = originalFileName; } public String getBizeType() { return bizeType; } public void setBizeType(String bizeType) { this.bizeType = bizeType; } public String getBizeId() { return bizeId; } public void setBizeId(String bizeId) { this.bizeId = bizeId; } public String getUploadUser() { return uploadUser; } public void setUploadUser(String uploadUser) { this.uploadUser = uploadUser; } public Date getUploadTime() { return uploadTime; } public void setUploadTime(Date uploadTime) { this.uploadTime = uploadTime; } public String getClient() { return client; } public void setClient(String client) { this.client = client; } @Override public String toString() { return "VirtualFile [size=" + size + ", suffix=" + suffix + ", filePath=" + filePath + ", fullFilePath=" + fullFilePath + ", originalFileName=" + originalFileName + ", bizeType=" + bizeType + ", bizeId=" + bizeId + ", uploadUser=" + uploadUser + ", uploadTime=" + uploadTime + ", client=" + client + "]"; } }
工具类 public class FileUtils { /** * 文件后缀 * * @param file * @return */ public static String getSuffix(File file) { return getSuffix(file.getName()); } /** * 后缀 * * @param fileName * @return */ public static String getSuffix(String fileName) { int index = fileName.lastIndexOf("."); index = -1 == index ? fileName.length() : index; return fileName.substring(index + 1); } /** * 文件后缀比较 */ public static final boolean allAssertSuffix(String suffix, String[] allSuffix) { return !StringUtils.isEmpty(suffix) && Arrays.asList(allSuffix).contains(suffix.toLowerCase()); } /** * 创建文件目录 * * @param baseDir * @param path * @return */ public static final File getAbsoluteFile(String dir, String path) { if (StringUtils.isEmpty(dir)) { return null; } File file = new File(dir + path); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } return file; } }
多媒体常量 public class MimeTypeConstants { public static final String IMAGE_PNG = "image/png"; public static final String IMAGE_JPG = "image/jpg"; public static final String IMAGE_JPEG = "image/jpeg"; public static final String IMAGE_BMP = "image/bmp"; public static final String IMAGE_GIF = "image/gif"; public static final String[] IMAGE_ALLOWED_EXTENSION = { // 图片 "jpg", "png", "bmp", "gif", "webp", "tiff" }; /** * 文件类型 */ public static final String[] DEFAULT_ALLOWED_EXTENSION = { // 图片 "jpg", "png", "bmp", "gif", "webp", "tiff", // word "doc", "docx", "xls", "xlsx", "txt", // 压缩文件 "rar", "zip", "gz", "bz2", }; public static String getExtension(String prefix) { switch (prefix) { case IMAGE_PNG: return "png"; case IMAGE_JPG: return "jpg"; case IMAGE_JPEG: return "jpeg"; case IMAGE_BMP: return "bmp"; case IMAGE_GIF: return "gif"; default: return ""; } } }
MinioClientApi public class MinioClientApi { private MinioClient minioClient; public MinioClientApi() { try { minioClient = new MinioClient("https://play.min.io", "Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG"); } catch (InvalidEndpointException | InvalidPortException e) { e.printStackTrace(); } } /** * 删除一个对象 * * @param bucketName * @param objectName */ public void removeObject(String bucketName, String objectName) { try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } minioClient.statObject(bucketName, objectName); minioClient.removeObject(bucketName, objectName); } catch (Exception e) { throw new MinioClientApiException(objectName + "上传对象异常", e); } } /** * 通过文件上传到对象中 * * @param bucketName * @param objectName * @param fileName */ public void putObject(String bucketName, String objectName, String fileName) { try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } minioClient.putObject(bucketName, objectName, fileName); } catch (Exception e) { throw new MinioClientApiException(objectName + "上传对象异常", e); } } /** * 通过InputStream上传对象 * * @param bucketName * @param objectName * @param stream * @param contentType */ public void putObject(String bucketName, String objectName, InputStream stream) { putObject(bucketName, objectName, stream, "application/octet-stream"); } /** * 通过InputStream上传对象 * * @param bucketName * @param objectName * @param stream * @param contentType */ public void putObject(String bucketName, String objectName, InputStream stream, String contentType) { try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } minioClient.putObject(bucketName, objectName, stream, stream.available(), contentType); } catch (Exception e) { throw new MinioClientApiException(objectName + "上传对象异常", e); } } /** * 下载并将文件保存到本地 * * @param bucketName * @param objectName * @param filePath */ public void getObject(String bucketName, String objectName, String fileName) { try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } // 调用statObject()来判断对象是否存在。 // 如果不存在, statObject()抛出异常, // 否则则代表对象存在。 minioClient.statObject(bucketName, objectName); minioClient.getObject(bucketName, objectName, fileName); } catch (Exception e) { throw new MinioClientApiException(objectName + "对象下载异常", e); } } /** * 以流的形式下载一个对象 * * @param bucketName * @param objectName * @return */ public InputStream getObject(String bucketName, String objectName) { InputStream stream = null; try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } // 调用statObject()来判断对象是否存在。 // 如果不存在, statObject()抛出异常, // 否则则代表对象存在。 minioClient.statObject(bucketName, objectName); stream = minioClient.getObject(bucketName, objectName); } catch (Exception e) { throw new MinioClientApiException(objectName + "对象下载异常", e); } finally { if (null != stream) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } return stream; } /** * 以流的形式下载一个对象,返回byte数组 * * @param bucketName * @param objectName * @return */ public byte[] getObjectByte(String bucketName, String objectName) { ByteArrayOutputStream out = null; BufferedInputStream in = null; try { boolean isExist = minioClient.bucketExists(bucketName); if (!isExist) { throw new MinioClientApiException(bucketName + "存储桶不存在"); } // 调用statObject()来判断对象是否存在。 // 如果不存在, statObject()抛出异常, // 否则则代表对象存在。 minioClient.statObject(bucketName, objectName); in = new BufferedInputStream(minioClient.getObject(bucketName, objectName)); out = new ByteArrayOutputStream(); byte[] bs = new byte[1024]; int n; while ((n = in.read(bs)) != -1) { out.write(bs, 0, n); } } catch (Exception e) { throw new MinioClientApiException(objectName + "对象下载异常", e); } finally { if (null != out) { try { out.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (null != in) { try { in.close(); } catch (IOException e1) { e1.printStackTrace(); } } } return out.toByteArray(); } }
MinioClientApi自定义异常 public class MinioClientApiException extends RuntimeException { private static final long serialVersionUID = 1L; private final String message; public MinioClientApiException(String message) { this.message = message; } public MinioClientApiException(String message, Throwable e) { super(message, e); this.message = message; } @Override public String getMessage() { return message; } }
热门排行