торговый центр интегрирует OSS для реализации загрузки файлов

Spring Boot

Резюме

В этой статье в основном объясняется процесс интеграции OSS с торговым центром для реализации загрузки файлов, который использует метод прямой загрузки через интерфейс после подписи сервера. Alibaba Cloud Object Storage Service (OSS) — это массивная, безопасная, недорогая и высоконадежная служба облачного хранения, предоставляемая Alibaba Cloud. OSS можно использовать для хранения больших файлов, таких как изображения, аудио и видео, а также журналы. Различные терминальные устройства, программы веб-сайтов и мобильные приложения могут напрямую записывать или считывать данные в OSS.

OSS

Alibaba Cloud Object Storage Service (OSS) — это массивная, безопасная, недорогая и высоконадежная служба облачного хранения, предоставляемая Alibaba Cloud. OSS можно использовать для хранения больших файлов, таких как изображения, аудио и видео, а также журналы. Различные терминальные устройства, программы веб-сайтов и мобильные приложения могут напрямую записывать или считывать данные в OSS.

Связанные понятия в OSS

  • Конечная точка: доступ к доменному имени, через которое вы можете получить доступ к API службы OSS и выполнять такие операции, как загрузка и скачивание файлов.
  • Ведро: Место для хранения — это контейнер для хранения объектов.Все объекты хранения должны принадлежать определенному пространству для хранения.
  • Объект: Объект.Объект является базовой единицей хранения данных OSS, также известной как файл OSS.
  • AccessKey: ключ доступа, который относится к AccessKeyId и AccessKeySecret, используемым при аутентификации доступа.

Настройки, связанные с OSS

Активировать услугу OSS

  • Войдите на официальный сайт Alibaba Cloud;
  • Переместите указатель мыши на вкладку продукта, щелкните Object Storage OSS и откройте страницу сведений о продукте OSS;
  • На странице сведений о продукте OSS нажмите Активировать сейчас.

Создать место для хранения

  • Нажмите кнопку консоли в правом верхнем углу веб-страницы, чтобы войти в консоль.

展示图片/arch_screen_77.png

  • Выберите Object Storage OSS в продуктах My Cloud

展示图片/arch_screen_78.png

  • Нажмите знак «плюс» слева от области хранения, чтобы создать новую область хранения.

展示图片/arch_screen_79.png

  • Создайте новое пространство для хранения и установите права на чтение и запись для общего чтения.

展示图片/arch_screen_80.png

Настройки общего доступа к ресурсам между источниками (CORS)

Поскольку браузер не разрешает междоменный доступ к ресурсам из соображений безопасности, нам необходимо настроить междоменное совместное использование ресурсов в OSS.

  • Выберите место для хранения, чтобы открыть его основные настройки

展示图片/arch_screen_81.png

  • Нажмите кнопку «Настройки», которая охватывает настройки

展示图片/arch_screen_82.png

  • Нажмите, чтобы создать правило

展示图片/arch_screen_83.png

  • Настройте междоменное правило

展示图片/arch_screen_84.png

Инструкции для прямой внешней передачи после подписи на стороне сервера

Диаграмма примера процесса

展示图片/arch_screen_85.png

Введение в процесс

  1. Веб-интерфейс запрашивает у сервера приложений параметры, необходимые для загрузки (например, OSS accessKeyId, политику, обратный вызов и другие параметры).
  2. Сервер приложений возвращает соответствующие параметры
  3. Веб-интерфейс напрямую инициирует запрос на загрузку файла в службу OSS.
  4. После завершения загрузки служба OSS вызовет интерфейс обратного вызова сервера приложений.
  5. Сервер приложений возвращает ответ службе OSS
  6. Служба OSS возвращает содержимое интерфейса обратного вызова сервера приложений в веб-интерфейс.

Интегрируйте OSS для реализации загрузки файлов

Добавьте связанные зависимости в pom.xml

<!-- OSS SDK 相关依赖 -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.5.0</version>
</dependency>

Измените файл конфигурации SpringBoot.

Измените файл application.yml и добавьте конфигурации, связанные с OSS.

Примечание. Конечная точка, accessKeyId, accessKeySecret, BucketName, обратный вызов и префикс должны быть изменены на те, которые относятся к вашей собственной учетной записи OSS, а обратный вызов должен быть адресом, доступным из общедоступной сети.

# OSS相关配置信息
aliyun:
  oss:
    endpoint: oss-cn-shenzhen.aliyuncs.com # oss对外服务的访问域名
    accessKeyId: test # 访问身份验证中用到用户标识
    accessKeySecret: test # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
    bucketName: macro-oss # oss的存储空间
    policy:
      expire: 300 # 签名有效期(S)
    maxSize: 10 # 上传文件大小(M)
    callback: http://localhost:8080/aliyun/oss/callback # 文件上传成功后的回调地址
    dir:
      prefix: mall/images/ # 上传文件夹路径前缀

Добавить связанную конфигурацию Java OSS

Клиент подключения OSSClient, используемый для настройки 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(){
        return new OSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET);
    }
}

Добавить объект пакета политики загрузки OSS OssPolicyResult

Параметры, необходимые, когда интерфейс загружает файлы напрямую, возвращаются из серверной части.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

/**
 * 获取OSS上传文件授权返回结果
 * Created by macro on 2018/5/17.
 */
public class OssPolicyResult {
    @ApiModelProperty("访问身份验证中用到用户标识")
    private String accessKeyId;
    @ApiModelProperty("用户表单上传的策略,经过base64编码过的字符串")
    private String policy;
    @ApiModelProperty("对policy签名后的字符串")
    private String signature;
    @ApiModelProperty("上传文件夹路径前缀")
    private String dir;
    @ApiModelProperty("oss对外服务的访问域名")
    private String host;
    @ApiModelProperty("上传成功后的回调设置")
    private String callback;

    //省略了所有getter,setter方法
}

Добавьте объект параметра обратного вызова OssCallbackParam после успешной загрузки OSS.

После успешной загрузки OSS соответствующий интерфейс будет вызван обратно в соответствии с параметром конфигурации.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

/**
 * oss上传成功后的回调参数
 * Created by macro on 2018/5/17.
 */
public class OssCallbackParam {
    @ApiModelProperty("请求的回调地址")
    private String callbackUrl;
    @ApiModelProperty("回调是传入request中的参数")
    private String callbackBody;
    @ApiModelProperty("回调时传入参数的格式,比如表单提交形式")
    private String callbackBodyType;

    //省略了所有getter,setter方法
}

Объект результата обратного вызова OssCallbackResult после успешной загрузки OSS

Объект данных, возвращаемый в интерфейсе обратного вызова, инкапсулирует информацию загруженного файла.

package com.macro.mall.tiny.dto;

import io.swagger.annotations.ApiModelProperty;

/**
 * oss上传文件的回调结果
 * Created by macro on 2018/5/17.
 */
public class OssCallbackResult {
    @ApiModelProperty("文件名称")
    private String filename;
    @ApiModelProperty("文件大小")
    private String size;
    @ApiModelProperty("文件的mimeType")
    private String mimeType;
    @ApiModelProperty("图片文件的宽")
    private String width;
    @ApiModelProperty("图片文件的高")
    private String height;

    //省略了所有getter,setter方法
}

Добавить бизнес-интерфейс OSS 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上传管理Service
 * Created by macro on 2018/5/17.
 */
public interface OssService {
    /**
     * oss上传策略生成
     */
    OssPolicyResult policy();

    /**
     * oss上传成功回调
     */
    OssCallbackResult callback(HttpServletRequest request);
}

Добавьте класс реализации OssServiceImpl бизнес-интерфейса OSS 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;

/**
 * oss上传管理Service实现类
 * 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;

	/**
	 * 签名生成
	 */
	@Override
	public OssPolicyResult policy() {
		OssPolicyResult result = new OssPolicyResult();
		// 存储目录
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
		String dir = ALIYUN_OSS_DIR_PREFIX+sdf.format(new Date());
		// 签名有效期
		long expireEndTime = System.currentTimeMillis() + ALIYUN_OSS_EXPIRE * 1000;
		Date expiration = new Date(expireEndTime);
		// 文件大小
		long maxSize = ALIYUN_OSS_MAX_SIZE * 1024 * 1024;
		// 回调
		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");
		// 提交节点
		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"));
			// 返回结果
			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("签名生成失败", 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"));
		return result;
	}

}

Добавить интерфейс определения OssController

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;

/**
 * Oss相关操作接口
 * Created by macro on 2018/4/26.
 */
@Controller
@Api(tags = "OssController", description = "Oss管理")
@RequestMapping("/aliyun/oss")
public class OssController {
    @Autowired
    private OssServiceImpl ossService;

    @ApiOperation(value = "oss上传签名生成")
    @RequestMapping(value = "/policy", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<OssPolicyResult> policy() {
        OssPolicyResult result = ossService.policy();
        return CommonResult.success(result);
    }

    @ApiOperation(value = "oss上传成功回调")
    @RequestMapping(value = "callback", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<OssCallbackResult> callback(HttpServletRequest request) {
        OssCallbackResult ossCallbackResult = ossService.callback(request);
        return CommonResult.success(ossCallbackResult);
    }

}

Проведите тестирование интерфейса

Протестируйте интерфейс для получения стратегии загрузки

展示图片/arch_screen_66.png

展示图片/arch_screen_67.png

展示图片/arch_screen_68.png

Запустите интерфейсный проект mall-admin-web, чтобы протестировать интерфейс загрузки.

  • Как начать интерфейсный проект, пожалуйста, обратитесь к документу readme проекта:GitHub.com/macro-positive/…

  • Нажмите кнопку загрузки, чтобы добавить марку продукта для тестирования.

展示图片/arch_screen_69.png

  • Запрос будет вызван дважды, при первом доступе к локальному интерфейсу для получения политики загрузки.

展示图片/arch_screen_70.png

展示图片/arch_screen_71.png

  • Второй раз вызвать интерфейс oss-сервиса для загрузки файлов

展示图片/arch_screen_72.png

展示图片/arch_screen_73.png

  • Можно видеть, что вышеуказанный вызов интерфейса не проходит в обратном вызове параметра обратного вызова, поэтому интерфейс возвращает 204 без содержимого. На этот раз мы передаем обратный вызов параметра обратного вызова и пробуем, мы можем обнаружить, что служба oss вызывает обратный вызов интерфейса мы определили и возвращает соответствующий результат.

展示图片/arch_screen_74.png

展示图片/arch_screen_75.png

展示图片/arch_screen_76.png

Адрес исходного кода проекта

GitHub.com/macro-positive/…

использованная литература

публика

проект торгового центраПолный набор учебных пособий сериализуется,Обратите внимание на публичный аккаунтПолучите это прямо сейчас.

公众号图片