Abstract

This paper mainly explains the process of mall integrating OSS to realize file upload, which adopts the way of front-end direct transmission after server signature. Ali Cloud Object Storage Service (OSS) is a massive, secure, low-cost and highly reliable cloud Storage Service provided by Ali Cloud. OSS can be used to store massive files such as pictures, audio and video files, and logs. Terminal devices, Web applications, and mobile applications can directly write or read data to OSS.

OSS

Ali Cloud Object Storage Service (OSS) is a massive, secure, low-cost and highly reliable cloud Storage Service provided by Ali Cloud. OSS can be used to store massive files such as pictures, audio and video files, and logs. Terminal devices, Web applications, and mobile applications can directly write or read data to OSS.

Related concepts in OSS

  • Endpoint: Access a domain name. You can use this domain name to access OSS service apis and upload and download files.
  • Bucket: a storage space. It is a container for storing objects. All objects must belong to a storage space.
  • Object: an Object is the basic unit of OSS data storage, also known as the OSS file.
  • AccessKey: AccessKey, which refers to the AccessKeyId and AccessKeySecret used in access authentication.

OSS related Settings

Enabling the OSS Service

  • Log in aliyun official website;
  • Move the mouse pointer to the product TAB and click object storage OSS. The OSS product details page is displayed.
  • On the OSS product details page, click Activate Now.

Creating Storage Space

  • Click the console button in the upper right corner of the page to access the console

  • Select object storage OSS in my cloud product

  • Click the plus sign of the storage space on the left to create storage space

  • Create storage space and set the read/write permission to public

Cross-domain resource sharing (CORS) Settings

For security reasons, browsers do not allow cross-domain resource access, so we need to set up cross-domain resource sharing of OSS.

  • Select a storage space and turn on its base Settings

  • Click the Settings button across Settings

  • Click Create rule

  • Set cross-domain rules

This section describes front-end direct transmission after server signature

Process sample diagram

The process is introduced

  1. The Web front-end requests the application server to obtain parameters required for uploading (such as accessKeyId, policy and callback of OSS).
  2. The application server returns related parameters
  3. The Web front-end directly sends file upload requests to the OSS service
  4. After the upload is complete, the OSS service calls back the callback interface of the application server
  5. The application server returns a response to the OSS service
  6. The OSS service returns the contents of the application server callback interface to the Web front end

Integrate OSS implementation file upload

Add related dependencies in pom.xml

<! -- OSS SDK dependencies -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.5.0</version>
</dependency>
Copy the code

Example Modify the SpringBoot configuration file

Modify the application.yml file to add OSS configurations.

Note: Set the endpoint, accessKeyId, accessKeySecret, bucketName, callback, and prefix to your own account OSS. Callback must be an address accessible to the public network.

# OSS configuration information
aliyun:
  oss:
    endpoint: oss-cn-shenzhen.aliyuncs.com Access domain name for oss external services
    accessKeyId: test Use the user id in access authentication
    accessKeySecret: test # key used by the user to encrypt the signature string and used by OSS to verify the signature string
    bucketName: macro-oss # Storage space for OSS
    policy:
      expire: 300 Signature validity period (S)
    maxSize: 10 # Upload file size (M)
    callback: http://localhost:8080/aliyun/oss/callback # callback address for successful file upload
    dir:
      prefix: mall/images/ # upload folder path prefix
Copy the code

Add the related Java configuration of OSS

The connection client OSSClient for configuring OSS.

package com.macro.mall.tiny.config;

import com.aliyun.oss.OSSClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** * Created by macro on 2018/5/17. */
@Configuration
public class OssConfig {
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.accessKeyId}")
    private String ALIYUN_OSS_ACCESSKEYID;
    @Value("${aliyun.oss.accessKeySecret}")
    private String ALIYUN_OSS_ACCESSKEYSECRET;
    @Bean
    public OSSClient ossClient(a){
        return newOSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET); }}Copy the code

The OSS upload policy encapsulation object OssPolicyResult is added

Parameters required by the front-end to upload files directly are returned from the back-end.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

** Created by macro on 2018/5/17. */
public class OssPolicyResult {
    @ApiModelProperty("User id used in access authentication")
    private String accessKeyId;
    @ApiModelProperty("User form upload policy, base64 encoded string.")
    private String policy;
    @ApiModelProperty("String after signing policy")
    private String signature;
    @ApiModelProperty("Upload folder path prefix")
    private String dir;
    @ApiModelProperty("Access domain name for OSS external Services")
    private String host;
    @ApiModelProperty("Callback Settings after successful upload")
    private String callback;

    // omits all getter,setter methods
}

Copy the code

Add OssCallbackParam, the callback parameter object after the OSS upload is successful

After the OSS uploads successfully, the interface is adjusted back and forth based on this parameter.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

** * Created by macro on 2018/5/17. */
public class OssCallbackParam {
    @ApiModelProperty("Requested callback address")
    private String callbackUrl;
    @ApiModelProperty("Callbacks are parameters passed into the request.")
    private String callbackBody;
    @ApiModelProperty("The format of the argument passed in for the callback, such as form submission.")
    private String callbackBodyType;

    // omits all getter,setter methods
}

Copy the code

The OssCallbackResult object is the result of the callback after the OSS upload

The data object returned in the callback interface that encapsulates information about the uploaded file.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

/** * Created by macro on 2018/5/17. */
public class OssCallbackResult {
    @ApiModelProperty("File Name")
    private String filename;
    @ApiModelProperty("File size")
    private String size;
    @ApiModelProperty("MimeType of file")
    private String mimeType;
    @ApiModelProperty("Image file width")
    private String width;
    @ApiModelProperty("Image file height")
    private String height;

    // omits all getter,setter methods
}

Copy the code

Add the OSS service interface OssService

package com.macro.mall.tiny.service;

import com.macro.mall.tiny.dto.OssCallbackResult;
import com.macro.mall.tiny.dto.OssPolicyResult;

import javax.servlet.http.HttpServletRequest;

/** * OSS upload management Service * Created by macro on 2018/5/17
public interface OssService {
    /** * OSS upload policy generated */
    OssPolicyResult policy(a);

    /** * OSS upload success callback */
    OssCallbackResult callback(HttpServletRequest request);
}

Copy the code

Add OssServiceImpl, the implementation class of the OSS service interface OssService

package com.macro.mall.tiny.service.impl;

import cn.hutool.json.JSONUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.macro.mall.tiny.dto.OssCallbackParam;
import com.macro.mall.tiny.dto.OssCallbackResult;
import com.macro.mall.tiny.dto.OssPolicyResult;
import com.macro.mall.tiny.service.OssService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;

/** * Created by macro on 2018/5/17. */
@Service
public class OssServiceImpl implements OssService {

	private static final Logger LOGGER = LoggerFactory.getLogger(OssServiceImpl.class);
	@Value("${aliyun.oss.policy.expire}")
	private int ALIYUN_OSS_EXPIRE;
	@Value("${aliyun.oss.maxSize}")
	private int ALIYUN_OSS_MAX_SIZE;
	@Value("${aliyun.oss.callback}")
	private String ALIYUN_OSS_CALLBACK;
	@Value("${aliyun.oss.bucketName}")
	private String ALIYUN_OSS_BUCKET_NAME;
	@Value("${aliyun.oss.endpoint}")
	private String ALIYUN_OSS_ENDPOINT;
	@Value("${aliyun.oss.dir.prefix}")
	private String ALIYUN_OSS_DIR_PREFIX;

	@Autowired
	private OSSClient ossClient;

	/** * Signature generated */
	@Override
	public OssPolicyResult policy(a) {
		OssPolicyResult result = new OssPolicyResult();
		// Store directory
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date());
		// Signature validity period
		long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
		Date expiration = new Date(expireEndTime);
		// File size
		long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
		/ / callback
		OssCallbackParam callback = new OssCallbackParam();
		callback.setCallbackUrl(ALIYUN_OSS_CALLBACK);
		callback.setCallbackBody("filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
		callback.setCallbackBodyType("application/x-www-form-urlencoded");
		// Submit the node
		String action = "http://" + ALIYUN_OSS_BUCKET_NAME + "." + ALIYUN_OSS_ENDPOINT;
		try {
			PolicyConditions policyConds = new PolicyConditions();
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, maxSize);
			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);
			String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
			byte[] binaryData = postPolicy.getBytes("utf-8");
			String policy = BinaryUtil.toBase64String(binaryData);
			String signature = ossClient.calculatePostSignature(postPolicy);
			String callbackData = BinaryUtil.toBase64String(JSONUtil.parse(callback).toString().getBytes("utf-8"));
			// Return the result
			result.setAccessKeyId(ossClient.getCredentialsProvider().getCredentials().getAccessKeyId());
			result.setPolicy(policy);
			result.setSignature(signature);
			result.setDir(dir);
			result.setCallback(callbackData);
			result.setHost(action);
		} catch (Exception e) {
			LOGGER.error("Signature generation failed", e);
		}
		return result;
	}

	@Override
	public OssCallbackResult callback(HttpServletRequest request) {
		OssCallbackResult result= new OssCallbackResult();
		String filename = request.getParameter("filename");
		filename = "http://".concat(ALIYUN_OSS_BUCKET_NAME).concat(".").concat(ALIYUN_OSS_ENDPOINT).concat("/").concat(filename);
		result.setFilename(filename);
		result.setSize(request.getParameter("size"));
		result.setMimeType(request.getParameter("mimeType"));
		result.setWidth(request.getParameter("width"));
		result.setHeight(request.getParameter("height"));
		returnresult; }}Copy the code

Add an OssController defining interface

package com.macro.mall.tiny.controller;


import com.macro.mall.tiny.common.api.CommonResult;
import com.macro.mall.tiny.dto.OssCallbackResult;
import com.macro.mall.tiny.dto.OssPolicyResult;
import com.macro.mall.tiny.service.impl.OssServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/** * Created by macro on 2018/4/26. */
@Controller
@Api(tags = "OssController", description = "The Oss management")
@RequestMapping("/aliyun/oss")
public class OssController {
    @Autowired
    private OssServiceImpl ossService;

    @ApiOperation(value = "Oss upload signature generation")
    @RequestMapping(value = "/policy", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<OssPolicyResult> policy(a) {
        OssPolicyResult result = ossService.policy();
        return CommonResult.success(result);
    }

    @ApiOperation(value = "Oss upload successful callback")
    @RequestMapping(value = "callback", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<OssCallbackResult> callback(HttpServletRequest request) {
        OssCallbackResult ossCallbackResult = ossService.callback(request);
        returnCommonResult.success(ossCallbackResult); }}Copy the code

Performing interface tests

Test the interface to get the upload policy

Start the mall-Admin-Web front end project to test the upload interface

  • For details on how to start the front-end project, see the readme document for the project: github.com/macrozheng/…

  • Click the Upload button to add a product brand to test it

  • Two requests are invoked, the first to access the local interface for the upload policy

  • Invoke the interface of the OSS service for the second time to upload files

  • The oss service calls our callback interface and returns a callback with 204 no content. If the oss service calls our callback interface with 204 no content, the oss service calls our callback interface with 204 no content.

Project source code address

Github.com/macrozheng/…

The resources

  • Enabling the OSS service: help.aliyun.com/document_de…

  • Create storage space: help.aliyun.com/document_de…

  • Cross-domain resource sharing (CORS) : help.aliyun.com/document_de…

  • Server signature direct passing back on and set the adjustment: help.aliyun.com/document_de…

The public,

Mall project full set of learning tutorials serialized, attention to the public number the first time access.