Reference: Java operation Ali Cloud OSS operation official documents
Learning to read documents and actually use them is also a habit and skill
Here is a simple introduction, with the current popular Springboot to operate Ali Cloud OSS file storage.
1. The demand
(If you haven’t stepped on the potholes below, you can skip this chapter.)
Questions briefly
First of all, I do some open source project cases in before he met some file upload download problem, such as in the native file upload and download can be normal use, through the upload files to Springboot root directory of the project, by date folder, file access is very convenient, also can be directly address returns the relative file path, and can be accessed directly.
The problem
However, this approach has drawbacks, because when the project package (JAR package) deployment ali Cloud student machine, there is a similar IO.NotFoundException… (No Such Directory), and if war package is deployed to Tomcat, there is No problem and it can be used normally. After a long investigation, the problem is found: The internal directory structure of the JAR package cannot be changed after packaging. That is, the file upload folder classified by date cannot be added to the JAR package when the folder of a new date needs to be created. In this case, IO exceptions will occur. For the WAR package in Tomcat, the war package will be decompressed automatically when Tomcat runs, and there is a real path on the server.
The solution
- Solution 1: I found a method on the Internet, which is to separate the file upload folder under the static springboot project after the deployment of the JAR package (equivalent to changing the relative path to the absolute path), and directly create a file upload folder under the same directory as the JAR package on the server when accessing it.
- Solution 2: Directly upload the file to the specified file upload location on the server. This method is also equivalent to using the absolute path.
- Scheme three: use FastDFS and Nginx on the server to build distributed file storage, this way is more complex, and students and the original memory and bandwidth is small, in their own computer virtual machine can try this scheme, or very good use, student server even.
- Solution 4: Upload files directly to the Ali Cloud OSS file storage system
2. Ali Cloud OSS purchase and configuration
This is relatively simple, recommend a blog to everyone to understand their own ali cloud OSS purchase and configuration, can also refer to ali cloud OSS official documents.
3. Springboot operates OSS
To create a Spring Boot project, the POM file needs to import dependencies:
pom.xml
<dependencies>
<! -- Personal version: Without this dependency, when using the @configurationProperties (prefix = "aliyun") annotation in the configuration class, my version of Spring Boot will tell you there is a problem -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<! -- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<! -- swagger ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<! -- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<! -- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<! -- Hot deployment, depending on personal habits -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<! JavaBean setters/getters can be saved, and chain calls can be used.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<! -- fastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<! -- aliyun-oos -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.1</version>
</dependency>
<! -- apache-common-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
Copy the code
The package structure is simple:
We use our own additionsapplication-aliyun-oss.propertiesYml (application. Yml) is not used to configure OSS related information in the configuration file. It is not necessary to configure all custom configuration properties in the application.
application-aliyun-oss.properties
# file upload size limit spring. Servlet. Multipart. Max - file - size = 100 MB spring. Servlet. Multipart. Max - request - size = 1000 MB # regional nodes Aliyun.endPoint=oss-cn-beijing.aliyuncs.com # Bucket domain name aliyun.urlprefix =http://csp-xxxx.oss-cn-beijing.aliyuncs.com/ # accessKey Id aliyun.accessKeyId=LTAI4XXXXXXXzqD1saGFZ # accessKey Secret aliyun.accessKeySecret=2WjxNXXXXXXXX4f2bREc # BucketName =csp-xxxx # Target folder aliyun.fileHost=filesCopy the code
Config package related configuration classes
AliyunOssConfig.java
/ * * *@Auther: csp1999
* @DateTemptation: 2020/10/31 / *@Description: Ali Cloud OSS basic configuration */
// Declare the configuration class and put it in the Spring container
@Configuration
// Specify the location of the configuration file
@PropertySource(value = {"classpath:application-aliyun-oss.properties"})
// Specify the custom attribute prefix in the configuration file
@ConfigurationProperties(prefix = "aliyun")
@Data// lombok
@Accessors(chain = true)// open the chain call
public class AliyunOssConfig {
private String endPoint;// Domain node
private String accessKeyId;
private String accessKeySecret;
private String bucketName;// The Bucket name of the OSS
private String urlPrefix;/ / Bucket domain name
private String fileHost;// Target folder
// Give the OSS client to the Spring container for hosting
@Bean
public OSS OSSClient(a) {
return newOSSClient(endPoint, accessKeyId, accessKeySecret); }}Copy the code
Swagger2Config.java
/ * * *@Auther: csp1999
* @Date: 2020/10/31 / ticket *@Description: Swagger configuration class */
@Configuration
@EnableSwagger2/ / open swagger2
public class Swagger2Config {
@Bean
public Docket webApiConfig(a) {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApi")
.apiInfo(webApiInfo())
.select()
.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build();
}
private ApiInfo webApiInfo(a) {
return new ApiInfoBuilder()
.title("SpringBoot integration with OSS-API documentation")
.description("Ali Cloud OSS- File upload and download test")
.version("1.0")
.contact(new Contact("CSP"."https://blog.csdn.net/weixin_43591980"."")) .build(); }}Copy the code
Define an enumeration class about the results of the execution state
/ * * *@Auther: csp1999
* @Date: 2020/10/31/17:03
* @Description: Status code enumeration class */
public enum StatusCode {
SUCCESS("success".200),ERROR("error".500);
private String msg;
private Integer code;
StatusCode(String msg,Integer code){
this.msg = msg;
this.code = code;
}
StatusCode(Integer code){
this.code = code;
}
StatusCode(String msg){
this.msg = msg;
}
public String getMsg(a) {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Integer getCode(a) {
return code;
}
public void setCode(Integer code) {
this.code = code; }}Copy the code
The service layer
Use ossClient to operate Ali cloud OSS in service, upload, download, delete, view all files and other operations, and at the same time, you can import the URL of the picture into the library:
FileUploadService.java
/ * * *@Auther: csp1999
* @Date: 2020/10/31 / passion *@Description: file upload Service (to save code space in this article, do not do interface implementation class processing) */
@Service("fileUploadService")
public class FileUploadService {
// Format that allows uploading of files (images)
private static final String[] IMAGE_TYPE = new String[]{".bmp".".jpg".".jpeg".".gif".".png"};
@Autowired
private OSS ossClient;// Inject ali Cloud OSS file server client
@Autowired
private AliyunOssConfig aliyunOssConfig;// Inject the Ali cloud OSS basic configuration class
Note: Ali Cloud OSS file upload official document link: https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.749.11987a7dRYVSzn * @ param: uploadFile * @return: string * @create: 2020/10/31 14:36 * @author: csp1999 */
public String upload(MultipartFile uploadFile) {
// Get the Bucket name of the OSS
String bucketName = aliyunOssConfig.getBucketName();
// Get the oss regional node
String endpoint = aliyunOssConfig.getEndPoint();
// Obtain AccessKeySecret for oss
String accessKeySecret = aliyunOssConfig.getAccessKeySecret();
// Obtain the AccessKeyId of the OSS
String accessKeyId = aliyunOssConfig.getAccessKeyId();
// Get the OSS target folder
String filehost = aliyunOssConfig.getFileHost();
// Returns the url returned after the image is uploaded
String returnImgeUrl = "";
// Verify the image format
boolean isLegal = false;
for (String type : IMAGE_TYPE) {
if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
isLegal = true;
break; }}if(! isLegal) {// If the image format is illegal
return StatusCode.ERROR.getMsg();
}
// Get the original file name
String originalFilename = uploadFile.getOriginalFilename();
// Get the file type
String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
// New file name
String newFileName = UUID.randomUUID().toString() + fileType;
// Build date path, for example: OSS target folder /2020/10/31/ file name
String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
// File upload path address
String uploadImgeUrl = filehost + "/" + filePath + "/" + newFileName;
// Get the file input stream
InputStream inputStream = null;
try {
inputStream = uploadFile.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
/** * The following two lines of code are key pits: * Now the default image upload ContentType of Ali Cloud OSS is image/ JPEG * that is to say, after retrieving the image link, the image is downloaded instead of browsing the link online. Change it to image/ JPG */
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("image/jpg");
// Upload the file to Ali Cloud OSS
ossClient.putObject(bucketName, uploadImgeUrl, inputStream, meta);
/** * Note: in a real project, after the file is successfully uploaded, the database stores the file address */
// Get the return address of the uploaded image of the file
returnImgeUrl = "http://" + bucketName + "." + endpoint + "/" + uploadImgeUrl;
return returnImgeUrl;
}
/* * File download * @param: fileName * @param: outputStream * @return: void * @create: 2020/10/31 16:19 * @author: csp1999 */
public String download(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
// // Sets the response header to download
// response.setContentType("application/x-download");
// // Set the file name for the download
// response.addHeader("Content-Disposition", "attachment; fileName=" + fileName);
// response.setCharacterEncoding("UTF-8");
// The file name is downloaded as an attachment
response.setHeader("Content-Disposition"."attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
// Get the Bucket name of the OSS
String bucketName = aliyunOssConfig.getBucketName();
// Get the OSS target folder
String filehost = aliyunOssConfig.getFileHost();
// Date directory
// Note that there is a logical problem with writing a fixed date directory, but in reality filePath's date directory should be queried from the database
String filePath = new DateTime().toString("yyyy/MM/dd");
String fileKey = filehost + "/" + filePath + "/" + fileName;
OssObject contains the name of the storage space where the file resides, the file name, the file meta-information, and an input stream.
OSSObject ossObject = ossClient.getObject(bucketName, fileKey);
try {
// Read the contents of the file.
InputStream inputStream = ossObject.getObjectContent();
BufferedInputStream in = new BufferedInputStream(inputStream);// stream the input to the cache stream
ServletOutputStream outputStream = response.getOutputStream();
BufferedOutputStream out = new BufferedOutputStream(outputStream);// Stream the output to the cache stream
byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) ! = -1) {
out.write(buffer, 0, len);
}
if(out ! =null) {
out.flush();
out.close();
}
if(in ! =null) {
in.close();
}
return StatusCode.SUCCESS.getMsg();
} catch (Exception e) {
returnStatusCode.ERROR.getMsg(); }}/* * File deleted * @param: objectName * @return: java.lang.String * @create: 2020/10/31 16:50 * @author: csp1999 */
public String delete(String fileName) {
// Get the Bucket name of the OSS
String bucketName = aliyunOssConfig.getBucketName();
// Get the oss regional node
String endpoint = aliyunOssConfig.getEndPoint();
// Obtain AccessKeySecret for oss
String accessKeySecret = aliyunOssConfig.getAccessKeySecret();
// Obtain the AccessKeyId of the OSS
String accessKeyId = aliyunOssConfig.getAccessKeyId();
// Get the OSS target folder
String filehost = aliyunOssConfig.getFileHost();
// Date directory
// Note that there is a logical problem with writing a fixed date directory, but in reality filePath's date directory should be queried from the database
String filePath = new DateTime().toString("yyyy/MM/dd");
try {
/** * Note: In a real project, there is no need to delete files in the OSS file server, * just delete the file path stored in the database! * /
// It is recommended to create OSSClient in the method instead of using @bean injection, otherwise the Connection pool will shut down easily
OSSClient ossClient = new OSSClient(endpoint,
accessKeyId, accessKeySecret);
// Delete files according to BucketName,filetName
// Delete files in the directory. If the last file is fileoath, the directory will be deleted.
String fileKey = filehost + "/" + filePath + "/" + fileName;
ossClient.deleteObject(bucketName, fileKey);
try{}finally {
ossClient.shutdown();
}
System.out.println("File deleted!");
return StatusCode.SUCCESS.getMsg();
} catch (Exception e) {
e.printStackTrace();
returnStatusCode.ERROR.getMsg(); }}}Copy the code
The controller layer
The controller provides the test interface
/ * * *@Auther: csp1999
* @Date: 2020/10/31 / they *@Description: OSS file upload controller */
@api (description = "ali cloud OSS file upload, download, delete Api ")
@RequestMapping("api/pri/file")
@RestController
public class OssFileController {
@Autowired
private FileUploadService fileUploadService;
File upload API / * * * @ param: file * @ return: com. Alibaba. Fastjson. JSONObject * @ the create: 2020/10/31 caught * @ author: csp1999 * /
@apiOperation (value = "file upload ")
@PostMapping("upload")
public JSONObject upload(@RequestParam("file") MultipartFile file) {
JSONObject jsonObject = new JSONObject();
if(file ! =null) {
String returnFileUrl = fileUploadService.upload(file);
if (returnFileUrl.equals("error")) {
jsonObject.put("error"."File upload failed!");
return jsonObject;
}
jsonObject.put("success"."File uploaded successfully!");
jsonObject.put("returnFileUrl", returnFileUrl);
return jsonObject;
} else {
jsonObject.put("error"."File upload failed!");
returnjsonObject; }}/ * * file download API * @ param: fileName * @ param: response * @ return: com. Alibaba. Fastjson. JSONObject * @ the create: 2020/10/31 17:35 * @author: csp1999 */
@apiOperation (value = "file download ")
@GetMapping(value = "download/{fileName}")
public JSONObject download(@PathVariable("fileName") String fileName, HttpServletResponse response) throws Exception {
JSONObject jsonObject = new JSONObject();
String status = fileUploadService.download(fileName, response);
if (status.equals("error")) {
jsonObject.put("error"."File download failed!");
return jsonObject;
} else {
jsonObject.put("success"."File downloaded successfully!");
returnjsonObject; }}/ * * * @ param file deletion API: fileName * @ return: com. Alibaba. Fastjson. JSONObject * @ the create: 2020/10/31 caught * @ the author: csp1999 */
@apiOperation (value = "delete file ")
@GetMapping("/delete/{fileName}")
public JSONObject DeleteFile(@PathVariable("fileName") String fileName) {
JSONObject jsonObject = new JSONObject();
String status = fileUploadService.delete(fileName);
if (status.equals("error")) {
jsonObject.put("error"."File deletion failed!");
return jsonObject;
} else {
jsonObject.put("success"."File deleted successfully!");
returnjsonObject; }}}Copy the code
4. Run the project test API
Native visit: http://localhost:8083/swagger-ui.html
Test upload:
The result is shown below:
If the upload is successful, let’s see if the link can be accessed:
Upload successful!
Source address: Gitee code repository
- If it is helpful to everyone, please support sanlian!
- Have a question welcome to leave a message in the comment area, help you solve in time!