京东OSS接入(使用AWS S3接口),理论上支持AWS S3接口通用

亡羊补牛
亡羊补牛 2019-05-28 08:05
阅读需:0

京东最近促销,买了做测试用还是不错的,OSS也是10GB免费,静态文件还是放OSS省心,外链访问,还不占用那可怜的服务器带宽,也可以把前端 的cdn放到oss上,下面开始:

假设你已经有京东账号

1、开通OSS服务,开通就可以了,后续创建bucket都自动创建


2、打开网页:https://docs.jdcloud.com/cn/object-storage-service/oss-endpont-list ,查看区域和端点对照表,等下配置京东OSS要使用


3、获取 

access-key  和  secret-key


点击京东控制台右上角用户名,进入账户管理。创建 Access Key,记下来


4、application.yml中添加jdoss 配置,endpoint 添加地区节点,bucket-name 存储空间名称全局唯一,如果京东已经存在同名的bucket,会创建失败,如果已经创建了bucket,直接填写你创建好的名字就可以了,region是bucket所在地区,这里是华东-上海区域


准备工作完成,开始代码部分


1、添加依赖,因为京东官方兼容AWS S3 api,所以依赖使用 Amazon S3 的SDK,最新版本 1.11.560


    com.amazonaws
    aws-java-sdk-s3
    1.11.560


2、modules 下创建一个oss包,添加 OssProperties 类,内容如下:

package org.springblade.modules.oss;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * Oss参数配置类
 *
 * @author Chill
 */
@Data
@ConfigurationProperties(prefix = "jdoss")
public class OssProperties {

   /**
    * 是否启用
    */
   private Boolean enable;

   /**
    * 对象存储名称
    */
   private String name;

   /**
    * 是否开启租户模式
    */
   private Boolean tenantMode;

   /**
    * 对象存储服务的URL
    */
   private String endpoint;

   /**
    * 对象存储服务的区域,默认“华东-上海”
    */
   private String region = "cn-east-2";

   /**
    * Access key就像用户ID,可以唯一标识你的账户
    */
   private String accessKey;

   /**
    * Secret key是你账户的密码
    */
   private String secretKey;

   /**
    * 默认的存储桶名称
    */
   private String bucketName = "stlscm";

   /**
    * 默认的文件前缀
    */
   private String prefix = "upload";

}


3、创建自动配置类 JdossConfiguration

package org.springblade.modules.oss;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Qiniu配置类
 *
 * @author Chill
 */
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnProperty(value = "jdoss.name", havingValue = "jdoss")
public class JdossConfiguration {

   private OssProperties ossProperties;

   @Bean
   @ConditionalOnMissingBean
   public AmazonS3 amazonS3() {
      ClientConfiguration config = new ClientConfiguration();
      AwsClientBuilder.EndpointConfiguration endpointConfig =
         new AwsClientBuilder.EndpointConfiguration(ossProperties.getEndpoint(), ossProperties.getRegion());
      AWSCredentials awsCredentials = new BasicAWSCredentials(ossProperties.getAccessKey(), ossProperties.getSecretKey());
      AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
      AmazonS3 s3 = AmazonS3Client.builder()
         .withEndpointConfiguration(endpointConfig)
         .withClientConfiguration(config)
         .withCredentials(awsCredentialsProvider)
         .disableChunkedEncoding()
         .withPathStyleAccessEnabled(true)
         .build();
      return s3;
   }

   @Bean
   @ConditionalOnMissingBean(JdossTemplate.class)
   @ConditionalOnBean({AmazonS3.class})
   public JdossTemplate jdossTemplate(OssProperties ossProperties, AmazonS3 amazonS3) {
      return new JdossTemplate(ossProperties, amazonS3);
   }

}


4、创建JdossTemplate 类

/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.oss;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.util.IOUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * QiniuTemplate
 *
 * @author Chill
 */
@AllArgsConstructor
public class JdossTemplate {

   private OssProperties ossProperties;

   private AmazonS3 amazonS3;

   @SneakyThrows
   public void makeBucket(String bucketName) {
      if (!bucketExists(bucketName)) {
         amazonS3.createBucket(bucketName);
      }
   }

   @SneakyThrows
   public boolean bucketExists(String bucketName) {
      List buckets = amazonS3.listBuckets();
      for (Bucket bucket : buckets) {
         if (bucket.getName().equals(bucketName)) {
            return true;
         }
      }
      return false;
   }

   @SneakyThrows
   public Map putFile(MultipartFile file) {
      return put(ossProperties.getBucketName(), file.getOriginalFilename(), file.getInputStream());
   }

   @SneakyThrows
   public Map put(String bucketName, String fileName, InputStream stream) {
      makeBucket(bucketName);
      fileName = getFileName(fileName);
      //上传这里的 objectMetadata.setContentLength 必须设置,否则报错,直接设置文件流的length也报错,京东官方没有说明,具体原因百度
      byte[] bytes = IOUtils.toByteArray(stream);
      ObjectMetadata objectMetadata = new ObjectMetadata();
      objectMetadata.setContentLength(bytes.length);
      objectMetadata.setContentType("application/octet-stream");
      ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
      // 上传
      amazonS3.putObject(bucketName, fileName, byteArrayInputStream, objectMetadata);
      Map rMap = new HashMap<>(2);
      rMap.put("fileName",fileName);
      rMap.put("url",ossProperties.getEndpoint().concat(StringPool.SLASH).concat(bucketName).concat(StringPool.SLASH).concat(fileName));
      return rMap;
   }

   /**
    * 根据规则生成文件名称规则
    *
    * @param originalFilename 原始文件名
    * @return string
    */
   private String getFileName(String originalFilename) {
      return StringUtil.randomUUID() + StringPool.DOT + originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
   }
}

最后添加一个测试类,测试上传,这个原始文件是冷总pigx里的,现在除了版权信息,都不是了。。。

/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the saintloong.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */

package org.springblade.modules.oss;

import io.swagger.annotations.Api;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.api.R;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lengleng
 * @date 2018-12-30
 * 

 * 文件管理  */ @Slf4j @RestController @AllArgsConstructor @RequestMapping("/file") @Api(value = "file", tags = "文件管理模块") public class FileController {    private final OssProperties jdossProperties;    private final JdossTemplate jdossTemplate;    /**     * 上传文件     *     * @param file 资源     * @return R(bucketName, filename)     */    @PostMapping("/upload-jd")    public R uploadJd(@RequestParam("file") MultipartFile file) {       return R.data(jdossTemplate.putFile(file));    } }


测试上传成功,源码压缩包附件上传,有懒人直接拿去。


oss.rar

这个是因为bladex作者翼总在bladex里面写了一个OSS集成功能,支持多租户,我自己扩展了一下,顺便提取出来上传部分,在blade-boot版本测试下,有需要的朋友可以直接拿来扩展,因为使用的 AWS S3接口的SDK,理论上支持AWS S3接口都可以这么用。

评论
  • 消灭零回复