Documentation

A good document is like an intriguing story.

Usage

以下所有配置和测试用例代码皆来自 dragonshard-sample

快速实现一个功能简单的本地对象存储服务。

为什么要提供一个如此"原始"的 starter 呢?
在传统行业,常常会有一些非常简单的信息化需求,这时要考虑的是如何最快最低成本的落地,不需要前后端分离、没有高并发、更没有服务拆分,让这个应用最大程度的保持简单。
配合 NAS,这个 starter 能立即提供一个配置即用的对象存储服务,满足最基础的文件上传、下载和图片预览。

v1.2.1:增加了基于 TinyPNG 的图片异步压缩,使用方法

                        Copy
                        
<dependency>
    <groupId>net.dragonshard</groupId>
    <artifactId>dragonshard-upload-local-starter</artifactId>
    <version>${latest.version}</version>
</dependency>
                        
                    

配置文件

                        Copy
                        
  upload:
    local:
      enabled: true
      compress:
        # 异步压缩(默认false)
        enabled: true
        # 当前仅支持 tinypng 压缩方式
        type: tinypng
      signature:
        # 签名校验(默认false)
        enabled: false
        # 签名用的密钥
        secret-key: bdb98f3eaeb7b966804b
        # 签名有效期
        timeout-second: 1800
      file:
        dir: upload_local
      url-prefix: http://localhost:21001/v1/api/upload/local/media/
                        
                    

配置项前缀dragonshard.upload.local

配置项 默认值 选项 描述
enabled true true / false 是否开启,默认 true
compress.enabled false true / false 是否开启异步压缩,默认 false
compress.type tinypng String 当前仅支持 tinypng 压缩方式
signature.enabled false true / false 是否开启签名校验,默认 false
signature.secret-key bdb98f3eaeb7b966804b String 密钥,一定要自行替换
signature.timeout-second 1800L Long 过期时间,默认30分钟
file.dir String 存储路径
url-prefix String 图片路径前缀,用于返回报文中拼接完整路径

Upload

如何控制上传对象的大小?

            Copy
            
# 通过 springboot 自身实现
spring:
  servlet:
    multipart:
      maxFileSize: "10MB"
            
          

在 controller 中的使用

            Copy
            
  @Autowired
  private IUploadLocalService uploadLocalService;

  /**
   * 上传文件
   *
   * @param uploadFile 文件
   * @param uploadBO 上传请求BO对象
   * @return httpResponse
   */
  @ApiOperation(value = "上传文件")
  @ApiImplicitParams({
    @ApiImplicitParam(name = "file", value = "待上传对象", required = true, paramType = "query")
  })
  @PostMapping("/upload")
  public ResponseEntity<Result<UploadResult>> upload(@RequestParam("file") MultipartFile uploadFile,
    @Validated UploadBO uploadBO) {
    try {
      return success(uploadLocalService.upload(uploadFile, uploadBO.convert(UploadRequest.class), uploadBO.getToken()));
    } catch (UploadTokenValidException e) {
      // 签名校验失败
      throw new BizException(BizErrorCodeEnum.UPLOAD_TOKEN_VALID_FAIL.convert());
    } catch (UploadTokenTimeoutException e) {
      // 签名超时
      throw new BizException(BizErrorCodeEnum.UPLOAD_TOKEN_TIMEOUT.convert());
    } catch (IOException e) {
      // 其它IO异常
      throw ExceptionUtils.get(e.getMessage());
    }
  }
            
          

在 dragonshard-sample 中提供了对应的完整用例, 在源码中查看

参数说明

参数名 必要 类型/可选项 描述
isCover Y Integer 同名文件是否覆盖, 0=否 1=是
否: 自动在原文件名字后增加时间戳(yyyyMMddHHmmssSS)
e.g. abc.png 重命名为 abc2019111415192873.png
fileName Y String 要存储的文件名称
token N String 签名,仅在开启签名校验时为必要参数
file Y MultipartFile 文件

打开 Postman,请求路径为localhost:21001/v1/api/upload/local/upload

上传完成后在 {PROJECT_PATH}/upload_local 可以看到对应的文件 upload_test_img_2M.jpg 和 upload_test_img_2M2019111509332323.jpg

开启签名校验之后,上传之前要生成签名,再作为token参数一同上传。

修改 dragonshard.upload.local.signature.enabled 为true

不要使用默认密钥,可以通过 EncryptUtils.generateAesKeyHex() 快速生成一个。

在 controller 中的使用,参数和上传是一样的。

            Copy
            
  @Autowired
  private IUploadLocalService uploadLocalService;

  /**
   * 预上传,返回Token
   *
   * @param uploadBO 上传请求BO对象
   * @return httpResponse
   */
  @GetMapping("/preload")
  public ResponseEntity<Result<UploadToken>> preload(@Validated UploadBO uploadBO) {
    return success(uploadLocalService.preload(uploadBO.convert(UploadRequest.class)));
  }
            
          

在 dragonshard-sample 中提供了对应的完整用例, 在源码中查看

生成 token 和时间戳,在开启签名校验的文件上传接口中,也要带上这两个参数。
token 会带有过期时间,默认30分钟,可在 dragonshard.upload.local.signature.timeout-second 修改。

            
{
    "status": "200",
    "data": {
        "token": "8c91b190641e09a3bd9e36ca8ae82d1e",
        "timestamp": "1573783670474"
    }
}
            
          

Preview

上传成功后返回的 url 字段就是图片预览地址,将其输入到浏览器地址栏中可直接下载。

Image Compress

此功能要求版本1.2.1+
这是一个starter联动功能,使用之前必须先引入 dragonshard-tinypng-starter 并在你的项目中自行实现 @EnableAsync 功能。
最终的压缩功能是调用 tinypng-starter 来实现的,如果没有实现异步则会改为同步压缩(不建议)。
压缩后会自动覆盖原文件,当前仅支持 TinyPNG 一种压缩实现,后期逐步丰富。

压缩测试

先将 tinypng-starter 中关键方法的日志输出级别改为DEBUG

            Copy
            
  <springProfile name="local,dev">
    <!--在logback-spring.xml中加入这行-->
    <logger name="net.dragonshard.dsf.tinypng.framework.service" level="DEBUG"/>

    <root level="info">
      <appender-ref ref="CONSOLE"/>
      <appender-ref ref="ASYNC_INFO_FILE"/>
    </root>
  </springProfile>
            
          

启动 dragonshard-sample 项目,上传在 upload_local 文件夹下事先准备好的图片 demo_img.jpeg(4KB),上传请求的参数设置为不要覆盖(isCover = 0),然后等一会,在控制台会看到:

Compression completed(9), total > 5.093s [upload_local/demo_img2019112908551233.jpeg]

括号内的数字代表已经使用的压缩次数(300张免费额度/月,同图片重复压缩不计次数)。找到新上传的图片,会发现大小是2KB,已经完成压缩。