├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── mvnsearch │ │ └── boot │ │ └── oss │ │ ├── AliyunOssAutoConfiguration.java │ │ ├── AliyunOssEndpoint.java │ │ ├── AliyunOssHealthIndicator.java │ │ ├── AliyunOssMetrics.java │ │ ├── AliyunOssProperties.java │ │ ├── ByteArrayDataSource.java │ │ ├── FileStorageService.java │ │ └── impl │ │ └── FileStorageServiceOssImpl.java └── resources │ └── META-INF │ ├── spring.factories │ └── spring.provides └── test ├── java └── org │ └── mvnsearch │ └── boot │ ├── AliyunOssAutoConfigurationTest.java │ └── OssTestApplication.java └── resources ├── 1.jpg ├── application.properties └── demo-context.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | *.class 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 14 | hs_err_pid* 15 | 16 | 17 | ### JetBrains template 18 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 19 | 20 | *.iml 21 | 22 | ## Directory-based project format: 23 | .idea/ 24 | # if you remove the above rule, at least ignore the following: 25 | 26 | # User-specific stuff: 27 | # .idea/workspace.xml 28 | # .idea/tasks.xml 29 | # .idea/dictionaries 30 | 31 | # Sensitive or high-churn files: 32 | # .idea/dataSources.ids 33 | # .idea/dataSources.xml 34 | # .idea/sqlDataSources.xml 35 | # .idea/dynamic.xml 36 | # .idea/uiDesigner.xml 37 | 38 | # Gradle: 39 | # .idea/gradle.xml 40 | # .idea/libraries 41 | 42 | # Mongo Explorer plugin: 43 | # .idea/mongoSettings.xml 44 | 45 | ## File-based project format: 46 | *.ipr 47 | *.iws 48 | 49 | ## Plugin-specific files: 50 | 51 | # IntelliJ 52 | out/ 53 | 54 | # mpeltonen/sbt-idea plugin 55 | .idea_modules/ 56 | 57 | # JIRA plugin 58 | atlassian-ide-plugin.xml 59 | 60 | # Crashlytics plugin (for Android Studio and IntelliJ) 61 | com_crashlytics_export_strings.xml 62 | crashlytics.properties 63 | crashlytics-build.properties 64 | 65 | 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | spring-boot-start-oss 2 | =================================== 3 | Spring boot with aliyun oss support 4 | 5 | ### usage 6 | in pom.xml add following dependency: 7 | 8 | 9 | org.mvnsearch.boot 10 | spring-boot-starter-oss 11 | 1.0.0-SNAPSHOT 12 | 13 | 14 | in application.properties file, please add following keys: 15 | 16 | spring.oss.key=xxxx 17 | spring.oss.secret=yyyy 18 | spring.oss.bucket=xxx-dev 19 | 20 | in your code you can use OssClient directly: 21 | 22 | @Autowired 23 | OSSClient ossClient; 24 | 25 | you can use FileStorageService API to operate file: 26 | 27 | @Autowired 28 | FileStorageService fileStorageService; 29 | 30 | ### Spring XML Configuration 31 | If you want to setup bean in Spring xml file, please use following code: 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ### spring-boot-start-oss service List 45 | 46 | * org.mvnsearch.boot.oss.FileStorageService: API to operate the file 47 | * com.aliyun.oss.OSSClient: aliyun OSSClient 48 | 49 | Please use FileStorageService as usual, not OSSClient. 50 | 51 | ### Aliyun OSS endpoint 52 | 53 | Please visit http://localhost:8080/oss to view detail information. 54 | 55 | 56 | ### FaQ 57 | 58 | * Please upload a "ok.txt" under your buket for health indicator. 59 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.mvnsearch.boot 7 | spring-boot-starter-oss 8 | 1.0.0-SNAPSHOT 9 | jar 10 | spring-boot-starter-oss 11 | https://github.com/linux-china/spring-boot-starter-oss 12 | 13 | 14 | UTF-8 15 | 1.3.3.RELEASE 16 | 2.5 17 | 2.2.1 18 | 19 | 20 | 21 | 22 | linux_china 23 | Jacky Chan 24 | libing.chen@gmail.com 25 | https://twitter.com/linux_china 26 | 27 | Developer 28 | 29 | 30 | 31 | 32 | 33 | scm:git:git@github.com:linux-china/spring-boot-starter-oss.git 34 | scm:git:git@github.com:linux-china/spring-boot-starter-oss.git 35 | https://github.com/linux-china/spring-boot-starter-oss 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-actuator 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-configuration-processor 46 | true 47 | 48 | 49 | commons-io 50 | commons-io 51 | ${commons-io.version} 52 | 53 | 54 | com.aliyun.oss 55 | aliyun-sdk-oss 56 | ${aliyun-oss.version} 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | junit 65 | junit 66 | test 67 | 68 | 69 | 70 | 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-dependencies 75 | ${spring-boot.version} 76 | pom 77 | import 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | maven-compiler-plugin 86 | 3.3 87 | 88 | 1.8 89 | 1.8 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/AliyunOssAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import com.aliyun.oss.OSSClient; 4 | import org.mvnsearch.boot.oss.impl.FileStorageServiceOssImpl; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 7 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 8 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | /** 13 | * aliyun oss auto configuration 14 | * 15 | * @author linux_china 16 | */ 17 | @Configuration 18 | @ConditionalOnClass(OSSClient.class) 19 | @EnableConfigurationProperties(AliyunOssProperties.class) 20 | public class AliyunOssAutoConfiguration { 21 | @SuppressWarnings("SpringJavaAutowiringInspection") 22 | @Autowired 23 | private AliyunOssProperties properties; 24 | 25 | @Bean 26 | @ConditionalOnMissingBean 27 | public OSSClient ossClient() { 28 | return new OSSClient(properties.getEndpoint(), properties.getKey(), properties.getSecret()); 29 | } 30 | 31 | @Bean 32 | @ConditionalOnMissingBean 33 | public FileStorageService fileStorageService() { 34 | FileStorageServiceOssImpl fileStorageServiceOss = new FileStorageServiceOssImpl(); 35 | fileStorageServiceOss.setAccessKey(properties.getKey()); 36 | fileStorageServiceOss.setAccessSecret(properties.getSecret()); 37 | fileStorageServiceOss.setBucketName(properties.getBucket()); 38 | return fileStorageServiceOss; 39 | } 40 | 41 | @Bean 42 | public AliyunOssHealthIndicator aliyunOssHealthIndicator() { 43 | return new AliyunOssHealthIndicator(); 44 | } 45 | 46 | @Bean 47 | public AliyunOssMetrics aliyunOssMetrics() { 48 | return new AliyunOssMetrics(); 49 | } 50 | 51 | @Bean 52 | public AliyunOssEndpoint aliyunOssEndpoint() { 53 | return new AliyunOssEndpoint(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/AliyunOssEndpoint.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import org.mvnsearch.boot.oss.impl.FileStorageServiceOssImpl; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.actuate.endpoint.AbstractEndpoint; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * aliyun OSS endpoint 13 | * 14 | * @author linux_china 15 | */ 16 | @ConfigurationProperties(prefix = "endpoints.aliyunoss", ignoreUnknownFields = false) 17 | public class AliyunOssEndpoint extends AbstractEndpoint { 18 | private AliyunOssProperties properties; 19 | 20 | public AliyunOssEndpoint() { 21 | super("oss", false, true); 22 | } 23 | 24 | @Autowired 25 | public void setTairProperties(AliyunOssProperties properties) { 26 | this.properties = properties; 27 | } 28 | 29 | public Object invoke() { 30 | Map info = new HashMap(); 31 | info.put("version", "2.2.1"); 32 | info.put("vendor", "http://www.aliyun.com/"); 33 | info.put("bucket", properties.getBucket()); 34 | info.put("upload.success", FileStorageServiceOssImpl.fileUploadSuccess.get()); 35 | info.put("upload.fail", FileStorageServiceOssImpl.fileUploadFail.get()); 36 | info.put("get.count", FileStorageServiceOssImpl.fileGetCounts.get()); 37 | info.put("delete.count", FileStorageServiceOssImpl.fileDeleteCounts.get()); 38 | return info; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/AliyunOssHealthIndicator.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.actuate.health.AbstractHealthIndicator; 5 | import org.springframework.boot.actuate.health.Health; 6 | import org.springframework.boot.actuate.health.HealthIndicator; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.activation.DataSource; 10 | 11 | /** 12 | * aliyun oss health indicator 13 | * 14 | * @author linux_china 15 | */ 16 | @Component 17 | public class AliyunOssHealthIndicator extends AbstractHealthIndicator { 18 | @Autowired 19 | private FileStorageService fileStorageService; 20 | 21 | protected void doHealthCheck(Health.Builder builder) throws Exception { 22 | DataSource ds = fileStorageService.get("ok.txt"); 23 | if (ds != null) { 24 | builder.up().withDetail("ok.txt", "Found"); 25 | } else { 26 | builder.down().withDetail("ok.txt", "Not found"); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/AliyunOssMetrics.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import org.mvnsearch.boot.oss.impl.FileStorageServiceOssImpl; 4 | import org.springframework.boot.actuate.endpoint.PublicMetrics; 5 | import org.springframework.boot.actuate.metrics.Metric; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Collection; 9 | import java.util.LinkedList; 10 | import java.util.List; 11 | 12 | /** 13 | * aliyun OSS metrics 14 | * 15 | * @author linux_china 16 | */ 17 | @Component 18 | public class AliyunOssMetrics implements PublicMetrics { 19 | 20 | public Collection> metrics() { 21 | List> metrics = new LinkedList>(); 22 | metrics.add(new Metric("oss.upload.success", FileStorageServiceOssImpl.fileUploadSuccess.get())); 23 | metrics.add(new Metric("oss.upload.fail", FileStorageServiceOssImpl.fileUploadFail.get())); 24 | metrics.add(new Metric("oss.get.count", FileStorageServiceOssImpl.fileGetCounts.get())); 25 | metrics.add(new Metric("oss.delete.count", FileStorageServiceOssImpl.fileDeleteCounts.get())); 26 | return metrics; 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/AliyunOssProperties.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | 5 | /** 6 | * aliyun oss properties 7 | * 8 | * @author linux_china 9 | */ 10 | @ConfigurationProperties( 11 | prefix = "spring.oss" 12 | ) 13 | public class AliyunOssProperties { 14 | /** 15 | * aliyun access key 16 | */ 17 | private String key; 18 | /** 19 | * aliyun access secret 20 | */ 21 | private String secret; 22 | /** 23 | * default bucket 24 | */ 25 | private String bucket; 26 | /** 27 | * endpoint 28 | */ 29 | private String endpoint = "http://oss.aliyuncs.com"; 30 | 31 | public String getKey() { 32 | return key; 33 | } 34 | 35 | public void setKey(String key) { 36 | this.key = key; 37 | } 38 | 39 | public String getSecret() { 40 | return secret; 41 | } 42 | 43 | public void setSecret(String secret) { 44 | this.secret = secret; 45 | } 46 | 47 | public String getBucket() { 48 | return bucket; 49 | } 50 | 51 | public void setBucket(String bucket) { 52 | this.bucket = bucket; 53 | } 54 | 55 | public String getEndpoint() { 56 | return endpoint; 57 | } 58 | 59 | public void setEndpoint(String endpoint) { 60 | this.endpoint = endpoint; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/ByteArrayDataSource.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | 4 | import java.io.*; 5 | import javax.activation.*; 6 | 7 | /** 8 | * A DataSource backed by a byte array. The byte array may be 9 | * passed in directly, or may be initialized from an InputStream 10 | * or a String. 11 | * 12 | * @author John Mani 13 | * @author Bill Shannon 14 | * @author Max Spivak 15 | * @since JavaMail 1.4 16 | */ 17 | public class ByteArrayDataSource implements DataSource { 18 | private byte[] data; // data 19 | private int len = -1; 20 | private String type; // content-type 21 | private String name = ""; 22 | 23 | static class DSByteArrayOutputStream extends ByteArrayOutputStream { 24 | public byte[] getBuf() { 25 | return buf; 26 | } 27 | 28 | public int getCount() { 29 | return count; 30 | } 31 | } 32 | 33 | /** 34 | * Create a ByteArrayDataSource with data from the 35 | * specified InputStream and with the specified MIME type. 36 | * The InputStream is read completely and the data is 37 | * stored in a byte array. 38 | * 39 | * @param is the InputStream 40 | * @param type the MIME type 41 | * @throws IOException errors reading the stream 42 | */ 43 | public ByteArrayDataSource(InputStream is, String type) throws IOException { 44 | DSByteArrayOutputStream os = new DSByteArrayOutputStream(); 45 | byte[] buf = new byte[8192]; 46 | int len; 47 | while ((len = is.read(buf)) > 0) 48 | os.write(buf, 0, len); 49 | this.data = os.getBuf(); 50 | this.len = os.getCount(); 51 | 52 | /* 53 | * ByteArrayOutputStream doubles the size of the buffer every time 54 | * it needs to expand, which can waste a lot of memory in the worst 55 | * case with large buffers. Check how much is wasted here and if 56 | * it's too much, copy the data into a new buffer and allow the 57 | * old buffer to be garbage collected. 58 | */ 59 | if (this.data.length - this.len > 256 * 1024) { 60 | this.data = os.toByteArray(); 61 | this.len = this.data.length; // should be the same 62 | } 63 | this.type = type; 64 | } 65 | 66 | /** 67 | * Create a ByteArrayDataSource with data from the 68 | * specified byte array and with the specified MIME type. 69 | * 70 | * @param data the data 71 | * @param type the MIME type 72 | */ 73 | public ByteArrayDataSource(byte[] data, String type) { 74 | this.data = data; 75 | this.type = type; 76 | } 77 | 78 | /** 79 | * Create a ByteArrayDataSource with data from the 80 | * specified String and with the specified MIME type. 81 | * The MIME type should include a charset 82 | * parameter specifying the charset to be used for the 83 | * string. If the parameter is not included, the 84 | * default charset is used. 85 | * 86 | * @param data the String 87 | * @param type the MIME type 88 | * @throws IOException errors reading the String 89 | */ 90 | public ByteArrayDataSource(String data, String type) throws IOException { 91 | this.data = data.getBytes(); 92 | this.type = type; 93 | } 94 | 95 | /** 96 | * Return an InputStream for the data. 97 | * Note that a new stream is returned each time 98 | * this method is called. 99 | * 100 | * @return the InputStream 101 | * @throws IOException if no data has been set 102 | */ 103 | public InputStream getInputStream() throws IOException { 104 | if (data == null) 105 | throw new IOException("no data"); 106 | if (len < 0) 107 | len = data.length; 108 | return new ByteArrayInputStream(data, 0, len); 109 | } 110 | 111 | /** 112 | * Return an OutputStream for the data. 113 | * Writing the data is not supported; an IOException 114 | * is always thrown. 115 | * 116 | * @throws IOException always 117 | */ 118 | public OutputStream getOutputStream() throws IOException { 119 | throw new IOException("cannot do this"); 120 | } 121 | 122 | /** 123 | * Get the MIME content type of the data. 124 | * 125 | * @return the MIME type 126 | */ 127 | public String getContentType() { 128 | return type; 129 | } 130 | 131 | /** 132 | * Get the name of the data. 133 | * By default, an empty string ("") is returned. 134 | * 135 | * @return the name of this data 136 | */ 137 | public String getName() { 138 | return name; 139 | } 140 | 141 | /** 142 | * Set the name of the data. 143 | * 144 | * @param name the name of this data 145 | */ 146 | public void setName(String name) { 147 | this.name = name; 148 | } 149 | } -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/FileStorageService.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss; 2 | 3 | import javax.activation.DataSource; 4 | import java.io.IOException; 5 | 6 | /** 7 | * file storage service 8 | * 9 | * @author linux_china 10 | */ 11 | public interface FileStorageService { 12 | 13 | /** 14 | * save file 15 | * 16 | * @param ds data source 17 | * @return file name 18 | * @throws IOException IO Exception 19 | */ 20 | public String save(DataSource ds) throws IOException; 21 | 22 | /** 23 | * save file to the directory 24 | * 25 | * @param directory directory 26 | * @param ds data source 27 | * @return file name with directory name 28 | * @throws IOException IO Exception 29 | */ 30 | public String saveToDirectory(String directory, DataSource ds) throws IOException; 31 | 32 | /** 33 | * delete file 34 | * 35 | * @param fileName file name 36 | * @throws IOException IO Exception 37 | */ 38 | public void delete(String fileName) throws IOException; 39 | 40 | /** 41 | * get file data source 42 | * 43 | * @param fileName file name 44 | * @return file data source 45 | * @throws IOException IO Exception 46 | */ 47 | public DataSource get(String fileName) throws IOException; 48 | 49 | public void rename(String oldName, String newName) throws IOException; 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/mvnsearch/boot/oss/impl/FileStorageServiceOssImpl.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot.oss.impl; 2 | 3 | import com.aliyun.oss.OSSClient; 4 | import com.aliyun.oss.model.OSSObject; 5 | import com.aliyun.oss.model.ObjectMetadata; 6 | import org.apache.commons.io.IOUtils; 7 | import org.mvnsearch.boot.oss.ByteArrayDataSource; 8 | import org.mvnsearch.boot.oss.FileStorageService; 9 | import org.springframework.beans.factory.InitializingBean; 10 | 11 | import javax.activation.DataSource; 12 | import javax.activation.MimetypesFileTypeMap; 13 | import java.io.ByteArrayInputStream; 14 | import java.io.IOException; 15 | import java.util.UUID; 16 | import java.util.concurrent.atomic.AtomicLong; 17 | 18 | /** 19 | * file storage service OSS implementation 20 | * 21 | * @author linux_china 22 | */ 23 | public class FileStorageServiceOssImpl implements FileStorageService, InitializingBean { 24 | String accessKey; 25 | String accessSecret; 26 | String bucketName; 27 | public static MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap(); 28 | public static String DEFAULT_CONTENT_TYPE = "application/octet-stream"; 29 | public static final AtomicLong fileUploadSuccess = new AtomicLong(); 30 | public static final AtomicLong fileUploadFail = new AtomicLong(); 31 | public static final AtomicLong fileGetCounts = new AtomicLong(); 32 | public static final AtomicLong fileDeleteCounts = new AtomicLong(); 33 | /** 34 | * oss client 35 | */ 36 | private OSSClient ossClient; 37 | 38 | public void setAccessKey(String accessKey) { 39 | this.accessKey = accessKey; 40 | } 41 | 42 | public void setAccessSecret(String accessSecret) { 43 | this.accessSecret = accessSecret; 44 | } 45 | 46 | public void setBucketName(String bucketName) { 47 | this.bucketName = bucketName; 48 | } 49 | 50 | @SuppressWarnings("deprecation") 51 | public void afterPropertiesSet() throws Exception { 52 | this.ossClient = new OSSClient(accessKey, accessSecret); 53 | } 54 | 55 | /** 56 | * save file 57 | * 58 | * @param ds data source 59 | * @return file name 60 | * @throws IOException IO Exception 61 | */ 62 | public String save(DataSource ds) throws IOException { 63 | String newName; 64 | newName = getUuidName(ds.getName()); 65 | byte[] content = IOUtils.toByteArray(ds.getInputStream()); 66 | upload(bucketName, newName, content); 67 | return newName; 68 | } 69 | 70 | /** 71 | * save file to the directory 72 | * 73 | * @param directory directory 74 | * @param ds data source 75 | * @return file name with directory name 76 | * @throws IOException IO Exception 77 | */ 78 | public String saveToDirectory(String directory, DataSource ds) throws IOException { 79 | String newName; 80 | newName = directory + "/" + getUuidName(ds.getName()); 81 | byte[] content = IOUtils.toByteArray(ds.getInputStream()); 82 | upload(bucketName, newName, content); 83 | return newName; 84 | } 85 | 86 | /** 87 | * delete file 88 | * 89 | * @param fileName file name 90 | * @throws IOException IO Exception 91 | */ 92 | public void delete(String fileName) throws IOException { 93 | ossClient.deleteObject(bucketName, fileName); 94 | fileDeleteCounts.incrementAndGet(); 95 | } 96 | 97 | /** 98 | * get file data source 99 | * 100 | * @param fileName file name 101 | * @return file data source 102 | * @throws IOException IO Exception 103 | */ 104 | public DataSource get(String fileName) throws IOException { 105 | OSSObject ossObject = ossClient.getObject(bucketName, fileName); 106 | if (ossObject != null) { 107 | ByteArrayDataSource ds = new ByteArrayDataSource(IOUtils.toByteArray(ossObject.getObjectContent()), getContentType(fileName)); 108 | ds.setName(fileName); 109 | fileGetCounts.incrementAndGet(); 110 | return ds; 111 | } 112 | return null; 113 | } 114 | 115 | 116 | public void rename(String oldName, String newName) throws IOException { 117 | boolean keyExists = true; 118 | try { 119 | ossClient.getObjectMetadata(bucketName, oldName); 120 | } catch (Exception e) { 121 | keyExists = false; 122 | } 123 | if (keyExists) { 124 | ossClient.copyObject(bucketName, oldName, bucketName, newName); 125 | } 126 | } 127 | 128 | public static String getUuidName(String name) { 129 | String uuid = UUID.randomUUID().toString().replaceAll("\\-", ""); 130 | String newName = uuid; 131 | if (name != null && name.contains(".")) { 132 | newName = uuid + name.substring(name.lastIndexOf(".")).toLowerCase(); 133 | } 134 | return newName; 135 | } 136 | 137 | /** 138 | * upload to bucket 139 | * 140 | * @param bucketName bucket name 141 | * @param fileName file name 142 | * @param content content 143 | */ 144 | private void upload(String bucketName, String fileName, byte[] content) throws IOException { 145 | ObjectMetadata metadata = new ObjectMetadata(); 146 | ByteArrayInputStream bis = new ByteArrayInputStream(content); 147 | try { 148 | metadata.setContentType(getContentType(fileName)); 149 | metadata.setContentLength(content.length); 150 | metadata.setCacheControl("public, max-age=31536000"); 151 | ossClient.putObject(bucketName, fileName, bis, metadata); 152 | fileUploadSuccess.incrementAndGet(); 153 | } catch (Exception ignore) { 154 | ossClient.putObject(bucketName, fileName, bis, metadata); 155 | fileUploadFail.incrementAndGet(); 156 | } 157 | } 158 | 159 | /** 160 | * get content type according to name or ext, default is "application/octet-stream" 161 | * 162 | * @param fileNameOrExt file name or ext name 163 | * @return content type 164 | */ 165 | public String getContentType(String fileNameOrExt) { 166 | if (fileNameOrExt == null || fileNameOrExt.isEmpty()) { 167 | return DEFAULT_CONTENT_TYPE; 168 | } 169 | return fileTypeMap.getContentType(fileNameOrExt.toLowerCase()); 170 | } 171 | 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | org.mvnsearch.boot.oss.AliyunOssAutoConfiguration 3 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.provides: -------------------------------------------------------------------------------- 1 | provides: spring-boot-starter-oss -------------------------------------------------------------------------------- /src/test/java/org/mvnsearch/boot/AliyunOssAutoConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot; 2 | 3 | import com.aliyun.oss.OSSClient; 4 | import org.apache.commons.io.IOUtils; 5 | import org.junit.After; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mvnsearch.boot.oss.AliyunOssAutoConfiguration; 11 | import org.mvnsearch.boot.oss.AliyunOssProperties; 12 | import org.mvnsearch.boot.oss.ByteArrayDataSource; 13 | import org.mvnsearch.boot.oss.FileStorageService; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; 16 | import org.springframework.boot.test.SpringApplicationConfiguration; 17 | import org.springframework.context.ApplicationContext; 18 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 19 | import org.springframework.context.annotation.Bean; 20 | import org.springframework.context.annotation.Configuration; 21 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 22 | 23 | import javax.activation.DataSource; 24 | 25 | /** 26 | * aliyun oss auto configuration test 27 | * 28 | * @author linux_china 29 | */ 30 | @RunWith(SpringJUnit4ClassRunner.class) 31 | @SpringApplicationConfiguration(classes = OssTestApplication.class) 32 | public class AliyunOssAutoConfigurationTest { 33 | @Autowired 34 | private ApplicationContext context; 35 | 36 | @Test 37 | public void clientExists() { 38 | Assert.assertEquals(1, this.context.getBeanNamesForType(OSSClient.class).length); 39 | Assert.assertEquals(1, this.context.getBeanNamesForType(FileStorageService.class).length); 40 | } 41 | 42 | @Test 43 | public void testSave() throws Exception { 44 | byte[] content = IOUtils.toByteArray(this.getClass().getResourceAsStream("/1.jpg")); 45 | ByteArrayDataSource bads = new ByteArrayDataSource(content, "image/jpeg"); 46 | bads.setName("1.jpg"); 47 | FileStorageService fileStorageService = context.getBean(FileStorageService.class); 48 | String newFileName = fileStorageService.save(bads); 49 | DataSource fileDS = fileStorageService.get(newFileName); 50 | Assert.assertNotNull(fileDS); 51 | fileStorageService.delete(newFileName); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/org/mvnsearch/boot/OssTestApplication.java: -------------------------------------------------------------------------------- 1 | package org.mvnsearch.boot; 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication; 4 | import org.springframework.context.annotation.ImportResource; 5 | import org.springframework.context.annotation.PropertySource; 6 | 7 | /** 8 | * oss test application 9 | * 10 | * @author linux_china 11 | */ 12 | @SpringBootApplication 13 | @PropertySource("/application.properties") 14 | public class OssTestApplication { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/resources/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linux-china/spring-boot-starter-oss/58120c5aeef82c56f90fe69959b5aa3c6ff8edca/src/test/resources/1.jpg -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.oss.key=xxxx 2 | spring.oss.secret=yyyy 3 | spring.oss.bucket=zzzz-dev -------------------------------------------------------------------------------- /src/test/resources/demo-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | --------------------------------------------------------------------------------