迁移文档到独立仓库。
1
.gitignore
vendored
@ -15,3 +15,4 @@ buildNumber.properties
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
/docs/.vitepress/cache/
|
||||
|
||||
142
README.md
@ -45,119 +45,7 @@ MinIO 的基础上只做增强,不侵入 MinIO 代码,只为简化开发、
|
||||
* **访问链接时效** :基于 MinIO 的临时链接创建策略,提供具备有效期并预签名的上传与下载地址。
|
||||
* **前端直连** :前端直连 MinIO ,项目工程不做文件流的搬运,在支持以上特性的情况下提供 MinIO 原生性能。
|
||||
|
||||
# 2 功能设计 | Function Design
|
||||
|
||||
项目定位为一个MinIO的Java语言SDK,非独立部署服务,并支持spring-boot自动装配。
|
||||
用户自行实现数据存储部分,项目仅提供MySQL默认实现。
|
||||
|
||||

|
||||
|
||||
* minio-plus-api:MinIO Plus 对外提供的能力接口定义,可以理解为 Service 层接口定义
|
||||
* minio-plus-core:核心业务逻辑包,可以理解为 minio-plus-api 包的接口实现
|
||||
* minio-plus-extension:扩展包,该包封装了Controller相关接口,可以理解为 minio-plus-api 包的接口的 Controller
|
||||
层封装,帮助项目使用时开箱即用
|
||||
* minio-plus-common:工具类、配置类包
|
||||
* minio-s3-api
|
||||
* minio-s3-api-definition:MinIO Plus 使用的S3规范接口定义
|
||||
* minio-s3-api-official:原生SDK实现
|
||||
* minio-s3-api-custom:自主实现
|
||||
* minio-plus-spring-boot-starter
|
||||
* minio-plus-all-spring-boot-starter:包含core、extension、common、api
|
||||
* minio-plus-core-spring-boot-starter:包含core、common、api
|
||||
* minio-plus-application
|
||||
* minio-plus-application-official:使用原生MinIO SDK与元数据使用MySQL数据库的示例工程
|
||||
* minio-plus-application-custom:使用自主实现S3规范与数据使用MySQL数据库的示例工程
|
||||
|
||||
## 2.1 文件下载 | File Download
|
||||
|
||||

|
||||
|
||||
浏览器向服务端发起文件读取请求,服务端会根据fileKey入参取得文件的元数据信息。获取文件元数据信息后,根据元数据信息中的是否私有字段和所有者字段判断是否具备文件读取权限。
|
||||
|
||||
* 当用户具备读取权限时,服务端请求MinIO服务器获取经过预签名的文件访问地址返回给浏览器。
|
||||
* 当用户不具备读取权限时,返回给浏览器无访问权限提示信息。
|
||||
|
||||
浏览器拿到真实文件地址后,读取文件并显示或下载。
|
||||
|
||||
## 2.2 文件上传 | File Upload
|
||||
|
||||
/TODO 上传流程活动图
|
||||
|
||||
### 2.2.1 秒传
|
||||
|
||||

|
||||
|
||||
当用户重复上传相同的文件时,每次都需要执行一次完整的文件上传操作,这造成了文件上传过程的冗余,即浪费了用户的时间和服务器的网络IO,重复文件又占用了不必要的服务器磁盘空间。
|
||||
针对以上两个问题,minio-plus支持文件秒传特性,解决了传统文件上传中重复文件上传时的问题,提高了文件传输的效率和用户体验,同时减少了文件服务器的存储空间占用。
|
||||
实现文件秒传的技术问题主要涉及文件唯一标识的生成和文件重复性检测。
|
||||
|
||||
* 文件唯一标识生成:在浏览器端,使用MD5哈希算法对待传输文件进行哈希值编码。编码结果为一字符串,作为文件的唯一标识。
|
||||
* 文件重复性检测:在服务器端,根据接收到的文件唯一标识在数据库中进行搜索。如果在数据库中找到相同的文件唯一标识,那么判断该文件存在且无需再进行文件传输。
|
||||
|
||||
### 2.2.2 分片上传
|
||||
|
||||
分片上传是一种将大文件划分为多个片段并发或按序上传的技术。它有以下几个好处:
|
||||
|
||||
* 提高传输速度:当上传的文件比较大时,将大文件进行分块,同时并发上传多个小块,而不是一整个大文件按顺序上传。这样可以最大限度地利用带宽,从而加快上传速度。
|
||||
* 支持断点续传:分块上传是断点续传技术的前置条件,要想实现断点续传,必须先支持分块。
|
||||
|
||||

|
||||
|
||||
### 2.2.3 断点续传
|
||||
|
||||
断点续传依赖于分片技术,是提高可用性的重要手段,优点如下:
|
||||
|
||||
* 节省时间、减少网络IO、减少磁盘IO:在文件传输过程中遇到问题导致传输失败时,只需重新传输未完成的分片,而不需要重新开始整个传输任务。
|
||||
* 增加传输的可靠性:可以避免由于网络波动或其他原因导致整个文件需要重新传输的情况。再也不怕意外断网。在大文件传输时,尤其有用。
|
||||
* 随时暂停和恢复:用户可以在传输过程中暂停传输或者中断传输,断点续传可以方便地恢复传输任务。
|
||||
|
||||
## 2.3 客户端直连
|
||||
|
||||
当用户进行文件流的上传和下载时,直接访问MinIO服务器(可配置Nginx代理)。
|
||||
|
||||
使用minioclient的GetPresignedObjectUrlArgs方法,入参是一个GetPresignedObjectUrlArgs对象,该对象包含了以下属性:
|
||||
|
||||
* bucketName:要访问的桶名。
|
||||
* objectName:要访问的对象名。
|
||||
* expires:URL的过期时间,单位为秒。
|
||||
|
||||
该方法的返回值是一个字符串类型的URL,可以用于访问指定的对象,示例:
|
||||
|
||||
```
|
||||
http://127.0.0.1:9000/test/test123
|
||||
?response-content-type=application%2Fmsword%22&response-content-disposition=attachment%3Bfilename%3D%22xxx.doc%22
|
||||
&X-Amz-Algorithm=AWS4-HMAC-SHA256
|
||||
&X-Amz-Credential=minioadmin%2F20230620%2Fus-east-1%2Fs3%2Faws4_request
|
||||
&X-Amz-Date=20230620T071735Z
|
||||
&X-Amz-Expires=60&X-Amz-SignedHeaders=host
|
||||
&X-Amz-Signature=5be3535042ffe72fedee8a283e7a5afbc2b068c595c16800cf57f089ed891cc5
|
||||
```
|
||||
|
||||
每次前端请求文件时,都会生成预签名文件地址,文件地址中,有日期、时效、签名。MinIO会进行验签,保证安全性。
|
||||
|
||||
## 2.4 缩略图
|
||||
|
||||

|
||||
|
||||
在用户第一次访问图片预览接口时自动生成缩略图,压缩时比例按照图片原始比例不做变化,使用相同的md5名称存入缩略图桶中。
|
||||
|
||||
* 缩略图:默认按照宽度300像素进行等比例压缩
|
||||
|
||||
PS:原图尺寸小于缩略图压缩尺寸时,储存原图。
|
||||
|
||||
## 2.5 桶策略
|
||||
|
||||
* 文档(document):txt、rtf、ofd、doc、docx、xls、xlsx、ppt、pptx、pdf
|
||||
* 压缩包(package):zip、rar、7z、tar、wim、gz、bz2
|
||||
* 音频( audio ):mp3、wav、flac、acc、ogg、aiff、m4a、wma、midi
|
||||
* 视频( video ):mp4、avi、mov、wmv、flv、mkv、mpeg、mpg 、rmvb
|
||||
* 图片 – 原始( image ):jpeg、jpg、png、bmp、webp、gif
|
||||
* 图片 – 缩略图( image-preview ):默认按照宽度 300 像素压缩缩
|
||||
* 其他( other ) :未在上述格式中的文件
|
||||
|
||||
其他规则:文件在桶中存储时,按照 /年/月 划分路径。用以规避Linux ext3文件系统下单个目录最多创建32000个目录的问题,参考了阿里云OSS的处理办法。
|
||||
|
||||
# 3 项目文档 | Document
|
||||
# 2 项目文档 | Document
|
||||
|
||||
* [首页](https://minioplus.liuxp.me/guide/intro.html)
|
||||
* [更新日志](https://minioplus.liuxp.me/guide/released.html)
|
||||
@ -188,39 +76,35 @@ PS:原图尺寸小于缩略图压缩尺寸时,储存原图。
|
||||
- [MinIO 分片 ETAG 生成机制](https://minioplus.liuxp.me/guide/study/etag.html)
|
||||
- [Nginx 代理](https://minioplus.liuxp.me/guide/study/proxy.html)
|
||||
|
||||
# 4 代码托管 | Managed Code
|
||||
*文档仓库地址*
|
||||
|
||||
* [https://gitee.com/lxp135/minio-plus-docs](https://gitee.com/lxp135/minio-plus-docs/)
|
||||
* [https://github.com/lxp135/minio-plus-docs](https://github.com/lxp135/minio-plus-docs/)
|
||||
|
||||
# 3 代码托管 | Managed Code
|
||||
|
||||
* [https://gitee.com/lxp135/minio-plus](https://gitee.com/lxp135/minio-plus/)
|
||||
* [https://github.com/lxp135/minio-plus](https://github.com/lxp135/minio-plus/)
|
||||
|
||||
以上仓库中代码完全一致,各位同学可根据网络状况自行选择。
|
||||
|
||||
# 5 版权 | License
|
||||
# 4 版权 | License
|
||||
|
||||
本项目基于 Apache License Version 2.0 开源协议,可用于商业项目。
|
||||
|
||||
协议内容:[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
# 6 参与贡献 | Credits
|
||||
# 5 参与贡献 | Credits
|
||||
|
||||
## 6.1 编写代码
|
||||
|
||||
* 在 Gitee Fork 项目到自己的仓库
|
||||
* 把 fork 过去的项目也就是你的项目 pull 到你的本地
|
||||
* 修改代码
|
||||
* commit 代码,push 到自己的库
|
||||
* 登录 Gitee 在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交
|
||||
* 等待维护者合并或者关闭
|
||||
|
||||
## 6.2 反馈问题
|
||||
## 5.1 反馈问题
|
||||
|
||||
欢迎提交**ISSUE**,请写清楚问题的具体原因,重现步骤和环境。
|
||||
|
||||
* Gitee Issue 地址 [https://gitee.com/lxp135/minio-plus/issues](https://gitee.com/lxp135/minio-plus/issues)
|
||||
* GitHub Issue 地址 [https://github.com/lxp135/minio-plus/issues](https://github.com/lxp135/minio-plus/issues)
|
||||
|
||||
## 6.3 微信群
|
||||
## 5.2 微信群
|
||||
|
||||

|
||||

|
||||
|
||||
如果二维码失效,可以加我的微信*movedisk_1*,我会手动拉您入群。
|
||||
如果二维码失效,可以加我的微信*movedisk_1*,我会手动拉您入群。
|
||||
@ -1,217 +0,0 @@
|
||||
import {defineConfig} from 'vitepress';
|
||||
|
||||
export default defineConfig({
|
||||
// 对 markdown 的配置
|
||||
markdown: {
|
||||
toc: {
|
||||
level: [1, 2, 3, 4], // 指定标题的层级
|
||||
}
|
||||
},
|
||||
locales: {
|
||||
root: {
|
||||
label: '简体中文',
|
||||
lang: 'zh',
|
||||
dir: 'src/zh',
|
||||
title: 'MinIO-Plus',
|
||||
description: '成为 MinIO 最好的搭档'
|
||||
},
|
||||
en: {
|
||||
label: 'English',
|
||||
lang: 'en',
|
||||
dir: 'src/en',
|
||||
title: 'MinIO-Plus',
|
||||
description: 'Be MinIO\'s best partner',
|
||||
themeConfig: {
|
||||
footer: {
|
||||
message: 'Publish under the <a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a>',
|
||||
copyright: 'Copyright © 2024 <a href="https://liuxp.me" target="_blank">liuxp.me</a>'
|
||||
},
|
||||
nav: [
|
||||
{text: 'INTRO', link: '/en/guide/intro', activeMatch: '/en/guide/'},
|
||||
{text: 'FAQ', link: '/en/faq/', activeMatch: '/en/faq/'},
|
||||
{text: 'DONATE', link: '/guide/donate'},
|
||||
],
|
||||
sidebar: {
|
||||
'/en/guide/': [
|
||||
{
|
||||
text: 'Getting Started',
|
||||
items: [
|
||||
{
|
||||
text: 'Introduction',
|
||||
link: '/en/guide/intro'
|
||||
},
|
||||
{
|
||||
text: 'Quick Start',
|
||||
link: '/en/guide/quick-start'
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
head: [
|
||||
['meta', {name: 'author', content: 'liuxp'}],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
name: 'keywords',
|
||||
content: 'minio, minio-plus minio tool'
|
||||
}
|
||||
],
|
||||
['link', {rel: 'icon', type: 'image/svg+xml', href: '/logo.svg'}],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
name: 'viewport',
|
||||
content: 'width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no'
|
||||
}
|
||||
],
|
||||
['link', {rel: 'icon', href: '/favicon.ico'}],
|
||||
['script',{},`!function(p){"use strict";!function(t){var s=window,e=document,i=p,c="".concat("https:"===e.location.protocol?"https://":"http://","sdk.51.la/js-sdk-pro.min.js"),n=e.createElement("script"),r=e.getElementsByTagName("script")[0];n.type="text/javascript",n.setAttribute("charset","UTF-8"),n.async=!0,n.src=c,n.id="LA_COLLECT",i.d=n;var o=function(){s.LA.ids.push(i)};s.LA?s.LA.ids&&o():(s.LA=p,s.LA.ids=[],o()),r.parentNode.insertBefore(n,r)}()}({id:"CDqGooQbS8dts6eI",ck:"CDqGooQbS8dts6eI",hashMode:true});`]
|
||||
],
|
||||
assetsDir: 'public',
|
||||
srcDir: 'src',
|
||||
themeConfig: {
|
||||
logo: '/logo.svg',
|
||||
socialLinks: [
|
||||
{icon: 'github', link: 'https://github.com/lxp135/minio-plus'},
|
||||
|
||||
],
|
||||
search: {
|
||||
provider: "algolia",
|
||||
options: {
|
||||
appId: "xxxx",
|
||||
apiKey: "xxx",
|
||||
indexName: "string",
|
||||
placeholder: "Search Doc",
|
||||
}
|
||||
},
|
||||
footer: {
|
||||
message: '根据 <a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank">Apache License 2.0</a> 许可证发布',
|
||||
copyright: 'Copyright © 2024 <a href="https://liuxp.me" target="_blank">liuxp.me</a>'
|
||||
},
|
||||
nav: [
|
||||
{text: '指引', link: '/guide/intro', activeMatch: '/zh/guide/'},
|
||||
{text: '常见问题', link: '/guide/references/faq', activeMatch: '/zh/faq/'},
|
||||
{text: '捐赠', link: '/guide/donate'},
|
||||
],
|
||||
sidebar: {
|
||||
'/guide/': [
|
||||
{
|
||||
text: '首页',
|
||||
link: '/guide/intro'
|
||||
},
|
||||
{
|
||||
text: '更新日志',
|
||||
link: '/guide/released'
|
||||
}, {
|
||||
text: '用户手册',
|
||||
items: [
|
||||
{
|
||||
text: '快速开始',
|
||||
link: '/guide/user/quick-start'
|
||||
},
|
||||
{
|
||||
text: 'API接口',
|
||||
link: '/guide/user/api'
|
||||
},
|
||||
{
|
||||
text: '文件元数据',
|
||||
link: '/guide/user/db'
|
||||
},
|
||||
{
|
||||
text: '配置文件',
|
||||
link: '/guide/user/config'
|
||||
},
|
||||
{
|
||||
text: '非官方S3实现',
|
||||
link: '/guide/user/custom'
|
||||
},
|
||||
]
|
||||
}, {
|
||||
text: '开发者手册',
|
||||
items: [
|
||||
{
|
||||
text: '开发计划',
|
||||
link: '/guide/developers/plan'
|
||||
},
|
||||
{
|
||||
text: '构建与运行',
|
||||
link: '/guide/developers/building'
|
||||
},
|
||||
{
|
||||
text: '代码结构',
|
||||
link: '/guide/developers/framework'
|
||||
},
|
||||
{
|
||||
text: '提交代码',
|
||||
link: '/guide/developers/writing-code'
|
||||
},
|
||||
{
|
||||
text: '编写文档',
|
||||
link: '/guide/developers/writing-documents'
|
||||
},
|
||||
{
|
||||
text: '贡献者列表',
|
||||
link: '/guide/developers/contributors'
|
||||
},
|
||||
]
|
||||
}, {
|
||||
text: '核心机制',
|
||||
items: [
|
||||
{
|
||||
text: '上传',
|
||||
link: '/guide/core/upload'
|
||||
},
|
||||
{
|
||||
text: '下载',
|
||||
link: '/guide/core/download'
|
||||
},
|
||||
{
|
||||
text: '客户端直连',
|
||||
link: '/guide/core/direct'
|
||||
},
|
||||
{
|
||||
text: '缩略图',
|
||||
link: '/guide/core/preview.md'
|
||||
},
|
||||
{
|
||||
text: '桶策略',
|
||||
link: '/guide/core/bucket'
|
||||
},
|
||||
{
|
||||
text: '权限控制',
|
||||
link: '/guide/core/auth'
|
||||
},
|
||||
]
|
||||
}, {
|
||||
text: '参考资料',
|
||||
items: [
|
||||
{
|
||||
text: 'FAQ',
|
||||
link: '/guide/references/faq'
|
||||
},
|
||||
{
|
||||
text: 'MinIO S3 接口',
|
||||
link: '/guide/references/minio-s3-api'
|
||||
}
|
||||
]
|
||||
}, {
|
||||
text: 'MinIO 研究',
|
||||
items: [
|
||||
{
|
||||
text: 'MinIO 分片 ETAG 生成机制',
|
||||
link: '/guide/study/etag'
|
||||
},
|
||||
{
|
||||
text: 'Nginx 代理',
|
||||
link: '/guide/study/proxy'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -1,32 +0,0 @@
|
||||
export const qqSvg = `
|
||||
<svg height="2500" viewBox="-1.94 0 124.879 145.085" width="2101" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m60.503 142.237c-12.533 0-24.038-4.195-31.445-10.46-3.762 1.124-8.574 2.932-11.61 5.175-2.6 1.918-2.275 3.874-1.807 4.663 2.056 3.47 35.273 2.216 44.862 1.136zm0 0c12.535 0 24.039-4.195 31.447-10.46 3.76 1.124 8.573 2.932 11.61 5.175 2.598 1.918 2.274 3.874 1.805 4.663-2.056 3.47-35.272 2.216-44.862 1.136zm0 0"
|
||||
fill="#faab07"
|
||||
/>
|
||||
<path
|
||||
d="m60.576 67.119c20.698-.14 37.286-4.147 42.907-5.683 1.34-.367 2.056-1.024 2.056-1.024.005-.189.085-3.37.085-5.01 0-27.634-13.044-55.401-45.124-55.402-32.08.001-45.125 27.769-45.125 55.401 0 1.642.08 4.822.086 5.01 0 0 .583.615 1.65.913 5.19 1.444 22.09 5.65 43.312 5.795zm56.245 23.02c-1.283-4.129-3.034-8.944-4.808-13.568 0 0-1.02-.126-1.537.023-15.913 4.623-35.202 7.57-49.9 7.392h-.153c-14.616.175-33.774-2.737-49.634-7.315-.606-.175-1.802-.1-1.802-.1-1.774 4.624-3.525 9.44-4.808 13.568-6.119 19.69-4.136 27.838-2.627 28.02 3.239.392 12.606-14.821 12.606-14.821 0 15.459 13.957 39.195 45.918 39.413h.848c31.96-.218 45.917-23.954 45.917-39.413 0 0 9.368 15.213 12.607 14.822 1.508-.183 3.491-8.332-2.627-28.021"
|
||||
/>
|
||||
<path
|
||||
d="m49.085 40.824c-4.352.197-8.07-4.76-8.304-11.063-.236-6.305 3.098-11.576 7.45-11.773 4.347-.195 8.064 4.76 8.3 11.065.238 6.306-3.097 11.577-7.446 11.771m31.133-11.063c-.233 6.302-3.951 11.26-8.303 11.063-4.35-.195-7.684-5.465-7.446-11.77.236-6.305 3.952-11.26 8.3-11.066 4.352.197 7.686 5.468 7.449 11.773"
|
||||
fill="#fff"
|
||||
/>
|
||||
<path
|
||||
d="m87.952 49.725c-1.162-2.575-12.875-5.445-27.374-5.445h-.156c-14.5 0-26.212 2.87-27.375 5.446a.863.863 0 0 0 -.085.367c0 .186.063.352.16.496.98 1.427 13.985 8.487 27.3 8.487h.156c13.314 0 26.319-7.058 27.299-8.487a.873.873 0 0 0 .16-.498.856.856 0 0 0 -.085-.365"
|
||||
fill="#faab07"
|
||||
/>
|
||||
<path
|
||||
d="m54.434 29.854c.199 2.49-1.167 4.702-3.046 4.943-1.883.242-3.568-1.58-3.768-4.07-.197-2.492 1.167-4.704 3.043-4.944 1.886-.244 3.574 1.58 3.771 4.07m11.956.833c.385-.689 3.004-4.312 8.427-2.993 1.425.347 2.084.857 2.223 1.057.205.296.262.718.053 1.286-.412 1.126-1.263 1.095-1.734.875-.305-.142-4.082-2.66-7.562 1.097-.24.257-.668.346-1.073.04-.407-.308-.574-.93-.334-1.362"
|
||||
/>
|
||||
<path
|
||||
d="m60.576 83.08h-.153c-9.996.12-22.116-1.204-33.854-3.518-1.004 5.818-1.61 13.132-1.09 21.853 1.316 22.043 14.407 35.9 34.614 36.1h.82c20.208-.2 33.298-14.057 34.616-36.1.52-8.723-.087-16.035-1.092-21.854-11.739 2.315-23.862 3.64-33.86 3.518"
|
||||
fill="#fff"
|
||||
/>
|
||||
<g fill="#eb1923">
|
||||
<path d="m32.102 81.235v21.693s9.937 2.004 19.893.616v-20.009c-6.307-.357-13.109-1.152-19.893-2.3" />
|
||||
<path
|
||||
d="m105.539 60.412s-19.33 6.102-44.963 6.275h-.153c-25.591-.172-44.896-6.255-44.962-6.275l-6.474 16.158c16.193 4.882 36.261 8.028 51.436 7.845h.153c15.175.183 35.242-2.963 51.437-7.845zm0 0"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
`;
|
||||
@ -1,4 +0,0 @@
|
||||
import Theme from 'vitepress/theme';
|
||||
import './style.css';
|
||||
|
||||
export default Theme;
|
||||
@ -1,106 +0,0 @@
|
||||
/**
|
||||
* Customize default theme styling by overriding CSS variables:
|
||||
* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css
|
||||
*/
|
||||
|
||||
/**
|
||||
* Colors
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-c-brand: #646cff;
|
||||
--vp-c-brand-light: #747bff;
|
||||
--vp-c-brand-lighter: #9499ff;
|
||||
--vp-c-brand-lightest: #bcc0ff;
|
||||
--vp-c-brand-dark: #535bf2;
|
||||
--vp-c-brand-darker: #454ce1;
|
||||
--vp-c-brand-dimm: rgba(100, 108, 255, 0.08);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Button
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-button-brand-border: var(--vp-c-brand-light);
|
||||
--vp-button-brand-text: var(--vp-c-white);
|
||||
--vp-button-brand-bg: var(--vp-c-brand);
|
||||
--vp-button-brand-hover-border: var(--vp-c-brand-light);
|
||||
--vp-button-brand-hover-text: var(--vp-c-white);
|
||||
--vp-button-brand-hover-bg: var(--vp-c-brand-light);
|
||||
--vp-button-brand-active-border: var(--vp-c-brand-light);
|
||||
--vp-button-brand-active-text: var(--vp-c-white);
|
||||
--vp-button-brand-active-bg: var(--vp-button-brand-bg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Home
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(
|
||||
120deg,
|
||||
var(--vp-c-brand-lightest) 30%,
|
||||
var(--vp-c-brand-darker)
|
||||
);
|
||||
|
||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, var(--vp-c-brand-lightest) 30%, var(--vp-c-brand) 50%);
|
||||
--vp-home-hero-image-filter: blur(40px);
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(56px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(72px);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Custom Block
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--vp-custom-block-tip-border: var(--vp-c-brand);
|
||||
--vp-custom-block-tip-text: var(--vp-c-brand-darker);
|
||||
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-custom-block-tip-border: var(--vp-c-brand);
|
||||
--vp-custom-block-tip-text: var(--vp-c-brand-lightest);
|
||||
--vp-custom-block-tip-bg: var(--vp-c-brand-dimm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Component: Algolia
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
.DocSearch {
|
||||
--docsearch-primary-color: var(--vp-c-brand) !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version Badge
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
.vt-badge {
|
||||
display: inline-block;
|
||||
border-radius: 6px;
|
||||
font-size: 0.65em;
|
||||
line-height: 1;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2px;
|
||||
padding: 0.35em 0.4em 0.3em;
|
||||
position: relative;
|
||||
top: -0.65em;
|
||||
margin-left: 0.5em;
|
||||
color: #ffffff;
|
||||
transition: color 0.5s;
|
||||
background-color: var(--vp-c-brand);
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
{
|
||||
"name": "MinIO-Plus-docs",
|
||||
"type": "module",
|
||||
"version": "1.0.0",
|
||||
"description": "The documentation of MinIO-Plus",
|
||||
"author": {
|
||||
"name": "BaldHead",
|
||||
"email": "tianxiang.deng@foxmail.com",
|
||||
"url": "https://github.com/bald-head"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vitepress dev --port 1026",
|
||||
"docs:build": "vitepress build",
|
||||
"preview": "vite preview",
|
||||
"release": "soy release",
|
||||
"serve": "vitepress serve"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@soybeanjs/cli": "1.0.13",
|
||||
"@types/node": "20.12.7",
|
||||
"typescript": "5.4.5",
|
||||
"vitepress": "^1.2.3"
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
<h1 align="center">MinIO Plus</h1>
|
||||
<h3 align="center">我们的愿景是成为 MinIO 最好的搭档</h3>
|
||||
|
||||
<p align="center">
|
||||
<a target="_blank" href="https://central.sonatype.com/search?q=me.liuxp.minio-plus-all-spring-boot-starter">
|
||||
<img src="https://img.shields.io/maven-central/v/me.liuxp/minio-plus-core.svg?label=Maven%20Central" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0">
|
||||
<img src="https://img.shields.io/badge/license-Apache%202-green.svg" alt="开源协议" />
|
||||
</a>
|
||||
<a target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-8+-red.svg" alt='JDK版本'/>
|
||||
</a>
|
||||
<a href='https://gitee.com/lxp135/minio-plus'>
|
||||
<img src='https://gitee.com/lxp135/minio-plus/badge/star.svg?theme=dark' alt='star' />
|
||||
</a>
|
||||
<a href="https://gitee.com/lxp135/minio-plus">
|
||||
<img src="https://gitee.com/lxp135/minio-plus/badge/fork.svg?theme=dark" alt="Gitee fork">
|
||||
</a>
|
||||
<br />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
# 0 简介 | Intro
|
||||
|
||||
[MinIO-Plus](https://gitee.com/lxp135/minio-plus/) 是一个 [MinIO](https://github.com/minio/minio) 的二次封装与增强工具,在
|
||||
MinIO 的基础上只做增强,不侵入 MinIO 代码,只为简化开发、提高效率而生。成为 MinIO 在项目中落地的润滑剂。
|
||||
@ -1,2 +0,0 @@
|
||||
# 快速开始
|
||||
|
||||
@ -1 +0,0 @@
|
||||
# 权限
|
||||
@ -1,11 +0,0 @@
|
||||
# 桶策略
|
||||
|
||||
* 文档(document):txt、rtf、ofd、doc、docx、xls、xlsx、ppt、pptx、pdf
|
||||
* 压缩包(package):zip、rar、7z、tar、wim、gz、bz2
|
||||
* 音频( audio ):mp3、wav、flac、acc、ogg、aiff、m4a、wma、midi
|
||||
* 视频( video ):mp4、avi、mov、wmv、flv、mkv、mpeg、mpg 、rmvb
|
||||
* 图片 – 原始( image ):jpeg、jpg、png、bmp、webp、gif
|
||||
* 图片 – 缩略图( image-preview ):默认按照宽度 300 像素压缩缩
|
||||
* 其他( other ) :未在上述格式中的文件
|
||||
|
||||
其他规则:文件在桶中存储时,按照 /年/月 划分路径。用以规避Linux ext3文件系统下单个目录最多创建32000个目录的问题,参考了阿里云OSS的处理办法。
|
||||
@ -1,23 +0,0 @@
|
||||
# 客户端直连
|
||||
|
||||
当用户进行文件流的上传和下载时,直接访问MinIO服务器(可配置Nginx代理)。
|
||||
|
||||
使用minioclient的GetPresignedObjectUrlArgs方法,入参是一个GetPresignedObjectUrlArgs对象,该对象包含了以下属性:
|
||||
|
||||
* bucketName:要访问的桶名。
|
||||
* objectName:要访问的对象名。
|
||||
* expires:URL的过期时间,单位为秒。
|
||||
|
||||
该方法的返回值是一个字符串类型的URL,可以用于访问指定的对象,示例:
|
||||
|
||||
```
|
||||
http://127.0.0.1:9000/test/test123
|
||||
?response-content-type=application%2Fmsword%22&response-content-disposition=attachment%3Bfilename%3D%22xxx.doc%22
|
||||
&X-Amz-Algorithm=AWS4-HMAC-SHA256
|
||||
&X-Amz-Credential=minioadmin%2F20230620%2Fus-east-1%2Fs3%2Faws4_request
|
||||
&X-Amz-Date=20230620T071735Z
|
||||
&X-Amz-Expires=60&X-Amz-SignedHeaders=host
|
||||
&X-Amz-Signature=5be3535042ffe72fedee8a283e7a5afbc2b068c595c16800cf57f089ed891cc5
|
||||
```
|
||||
|
||||
每次前端请求文件时,都会生成预签名文件地址,文件地址中,有日期、时效、签名。MinIO会进行验签,保证安全性。
|
||||
@ -1,10 +0,0 @@
|
||||
# 下载
|
||||
|
||||

|
||||
|
||||
浏览器向服务端发起文件读取请求,服务端会根据fileKey入参取得文件的元数据信息。获取文件元数据信息后,根据元数据信息中的是否私有字段和所有者字段判断是否具备文件读取权限。
|
||||
|
||||
* 当用户具备读取权限时,服务端请求MinIO服务器获取经过预签名的文件访问地址返回给浏览器。
|
||||
* 当用户不具备读取权限时,返回给浏览器无访问权限提示信息。
|
||||
|
||||
浏览器拿到真实文件地址后,读取文件并显示或下载。
|
||||
@ -1,9 +0,0 @@
|
||||
# 缩略图
|
||||
|
||||

|
||||
|
||||
在用户第一次访问图片预览接口时自动生成缩略图,压缩时比例按照图片原始比例不做变化,使用相同的md5名称存入缩略图桶中。
|
||||
|
||||
* 缩略图:默认按照宽度300像素进行等比例压缩
|
||||
|
||||
PS:原图尺寸小于缩略图压缩尺寸时,储存原图。
|
||||
@ -1,31 +0,0 @@
|
||||
# 上传
|
||||
|
||||
/TODO 上传流程活动图
|
||||
|
||||
## 秒传
|
||||
|
||||

|
||||
|
||||
当用户重复上传相同的文件时,每次都需要执行一次完整的文件上传操作,这造成了文件上传过程的冗余,即浪费了用户的时间和服务器的网络IO,重复文件又占用了不必要的服务器磁盘空间。
|
||||
针对以上两个问题,minio-plus支持文件秒传特性,解决了传统文件上传中重复文件上传时的问题,提高了文件传输的效率和用户体验,同时减少了文件服务器的存储空间占用。
|
||||
实现文件秒传的技术问题主要涉及文件唯一标识的生成和文件重复性检测。
|
||||
|
||||
* 文件唯一标识生成:在浏览器端,使用MD5哈希算法对待传输文件进行哈希值编码。编码结果为一字符串,作为文件的唯一标识。
|
||||
* 文件重复性检测:在服务器端,根据接收到的文件唯一标识在数据库中进行搜索。如果在数据库中找到相同的文件唯一标识,那么判断该文件存在且无需再进行文件传输。
|
||||
|
||||
## 分片上传
|
||||
|
||||
分片上传是一种将大文件划分为多个片段并发或按序上传的技术。它有以下几个好处:
|
||||
|
||||
* 提高传输速度:当上传的文件比较大时,将大文件进行分块,同时并发上传多个小块,而不是一整个大文件按顺序上传。这样可以最大限度地利用带宽,从而加快上传速度。
|
||||
* 支持断点续传:分块上传是断点续传技术的前置条件,要想实现断点续传,必须先支持分块。
|
||||
|
||||

|
||||
|
||||
## 断点续传
|
||||
|
||||
断点续传依赖于分片技术,是提高可用性的重要手段,优点如下:
|
||||
|
||||
* 节省时间、减少网络IO、减少磁盘IO:在文件传输过程中遇到问题导致传输失败时,只需重新传输未完成的分片,而不需要重新开始整个传输任务。
|
||||
* 增加传输的可靠性:可以避免由于网络波动或其他原因导致整个文件需要重新传输的情况。再也不怕意外断网。在大文件传输时,尤其有用。
|
||||
* 随时暂停和恢复:用户可以在传输过程中暂停传输或者中断传输,断点续传可以方便地恢复传输任务。
|
||||
@ -1 +0,0 @@
|
||||
# 构建与运行
|
||||
@ -1,4 +0,0 @@
|
||||
# 贡献者列表
|
||||
|
||||
* contact@liuxp.me
|
||||
* tianxiang.deng@foxmail.com
|
||||
@ -1,25 +0,0 @@
|
||||
# 代码结构
|
||||
|
||||
项目定位为一个MinIO的Java语言SDK,非独立部署服务,并支持spring-boot自动装配。
|
||||
用户自行实现数据存储部分,项目仅提供MySQL默认实现。
|
||||
|
||||
## 模块划分
|
||||

|
||||
|
||||
* minio-plus-api:MinIO Plus 对外提供的能力接口定义,可以理解为 Service 层接口定义
|
||||
* minio-plus-core:核心业务逻辑包,可以理解为 minio-plus-api 包的接口实现
|
||||
* minio-plus-extension:扩展包,该包封装了Controller相关接口,可以理解为 minio-plus-api 包的接口的 Controller
|
||||
层封装,帮助项目使用时开箱即用
|
||||
* minio-plus-common:工具类、配置类包
|
||||
* minio-s3-api
|
||||
* minio-s3-api-definition:MinIO Plus 使用的S3规范接口定义
|
||||
* minio-s3-api-official:原生SDK实现
|
||||
* minio-s3-api-custom:自主实现
|
||||
* minio-plus-spring-boot-starter
|
||||
* minio-plus-all-spring-boot-starter:包含core、extension、common、api
|
||||
* minio-plus-core-spring-boot-starter:包含core、common、api
|
||||
* minio-plus-application
|
||||
* minio-plus-application-official:使用原生MinIO SDK与元数据使用MySQL数据库的示例工程
|
||||
* minio-plus-application-custom:使用自主实现S3规范与数据使用MySQL数据库的示例工程
|
||||
|
||||
## 包的划分
|
||||
@ -1,3 +0,0 @@
|
||||
# 开发计划
|
||||
|
||||

|
||||
@ -1,21 +0,0 @@
|
||||
# 提交代码
|
||||
|
||||
## 推送代码
|
||||
|
||||
* 在 Gitee Fork 项目到自己的仓库
|
||||
* 把 fork 过去的项目也就是你的项目 pull 到你的本地
|
||||
* 修改代码
|
||||
* commit 代码,push 到自己的库
|
||||
* 登录 Gitee 在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交
|
||||
* 等待维护者合并或者关闭
|
||||
|
||||
## 反馈问题
|
||||
|
||||
欢迎提交**ISSUE**,请写清楚问题的具体原因,重现步骤和环境。
|
||||
|
||||
* Gitee Issue 地址 [https://gitee.com/lxp135/minio-plus/issues](https://gitee.com/lxp135/minio-plus/issues)
|
||||
* GitHub Issue 地址 [https://github.com/lxp135/minio-plus/issues](https://github.com/lxp135/minio-plus/issues)
|
||||
|
||||
## 加入我们
|
||||
|
||||
也欢迎各位朋友直接加入项目,进行长期开发。
|
||||
@ -1,42 +0,0 @@
|
||||
# 编写文档
|
||||
|
||||
本项目使用 vitepress 进行文档编写,文档保存在项目仓库的/docs路径下。
|
||||
|
||||
## 编译文档工程
|
||||
|
||||
### 安装yarn
|
||||
```
|
||||
npm install -g yarn
|
||||
```
|
||||
### 安装vitepress
|
||||
```
|
||||
yarn add --dev vitepress
|
||||
```
|
||||
### 启动
|
||||
```
|
||||
yarn dev
|
||||
```
|
||||
|
||||
### 常见问题
|
||||
|
||||
#### 安装 vitepress 提示 node 版本错误,如何切换 node 版本
|
||||
|
||||
访问 nvm-windows 的 [GitHub](https://github.com/coreybutler/nvm-windows) 页面。
|
||||
下载并安装nvm-windows。
|
||||
安装完成后,打开命令行(例如PowerShell或CMD)。
|
||||
查看所有可用的Node.js版本:
|
||||
```
|
||||
nvm list available
|
||||
```
|
||||
安装你想要的Node.js版本,例如:
|
||||
```
|
||||
nvm install 18.18.0
|
||||
```
|
||||
使用你刚刚安装的版本:
|
||||
```
|
||||
nvm use 18.18.0
|
||||
```
|
||||
验证是否成功切换到新版本:
|
||||
```
|
||||
node -v
|
||||
```
|
||||
@ -1 +0,0 @@
|
||||
# 捐赠
|
||||
@ -1,73 +0,0 @@
|
||||
<h1 align="center">MinIO Plus</h1>
|
||||
<h3 align="center">我们的愿景是成为 MinIO 最好的搭档</h3>
|
||||
<p>
|
||||
<a style="float: left;padding-left:110px;padding-right: 5px;" target="_blank" href="https://central.sonatype.com/search?q=me.liuxp.minio-plus-all-spring-boot-starter">
|
||||
<img src="https://img.shields.io/maven-central/v/me.liuxp/minio-plus-core.svg?label=Maven%20Central" />
|
||||
</a>
|
||||
<a style="float: left;padding-right: 5px;" target="_blank" href="https://www.apache.org/licenses/LICENSE-2.0">
|
||||
<img src="https://img.shields.io/badge/license-Apache%202-green.svg" alt="开源协议" />
|
||||
</a>
|
||||
<a style="float: left;padding-right: 5px;" target="_blank" href="https://www.oracle.com/technetwork/java/javase/downloads/index.html">
|
||||
<img src="https://img.shields.io/badge/JDK-8+-red.svg" alt='JDK版本'/>
|
||||
</a>
|
||||
<a style="float: left;padding-right: 5px;" href='https://gitee.com/lxp135/minio-plus'>
|
||||
<img src='https://gitee.com/lxp135/minio-plus/badge/star.svg?theme=dark' alt='star' />
|
||||
</a>
|
||||
<a style="float: left;padding-right: 5px;" href="https://gitee.com/lxp135/minio-plus">
|
||||
<img src="https://gitee.com/lxp135/minio-plus/badge/fork.svg?theme=dark" alt="Gitee fork">
|
||||
</a>
|
||||
<br />
|
||||
</p>
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 介绍
|
||||
|
||||
[MinIO-Plus](https://gitee.com/lxp135/minio-plus/) 是一个 [MinIO](https://github.com/minio/minio) 的二次封装与增强工具,在
|
||||
MinIO 的基础上只做增强,不侵入 MinIO 代码,只为简化开发、提高效率而生。成为 MinIO 在项目中落地的润滑剂。
|
||||
|
||||
---
|
||||
|
||||
# 特性
|
||||
|
||||
* **无侵入** :只做增强不做改变,引入 `minio-plus` 不会对现有工程产生影响。
|
||||
* **文件秒传** :对每个上传的文件进行哈希摘要识别,用户上传同一个文件时,没有文件实际传输过程,做到秒传。
|
||||
* **并发上传** :将文件切分为小块。同时并发上传多个小块,最大限度地利用带宽,加快上传速度。
|
||||
* **断点续传** :在传输过程中遇到问题导致传输失败,只需重新传输未完成的小块,而不需要重新开始整个传输任务。
|
||||
* **缩略图生成** :识别文件类型,在图片上传时自动生成缩略图,缩略图大小可配置。
|
||||
* **自动桶策略** :按照文档、压缩包、音频、视频、图片等类型自动建桶,按照 `/年/月` 划分路径,避免受到操作系统文件目录体系影响导致性能下降。
|
||||
* **访问权限控制** :可支持基于用户、组的文件权限控制,保证重要文件的安全性。
|
||||
* **访问链接时效** :基于 MinIO 的临时链接创建策略,提供具备有效期并预签名的上传与下载地址。
|
||||
* **客户端直连** :前端直连 MinIO ,项目工程不做文件流的搬运,在支持以上特性的情况下提供 MinIO 原生性能。
|
||||
|
||||
# 文档目录
|
||||
|
||||
* [首页](intro)
|
||||
* [更新日志](released.md)
|
||||
* 用户手册
|
||||
- [快速开始](user/quick-start)
|
||||
- [API接口](user/api)
|
||||
- [文件元数据](user/db)
|
||||
- [配置文件](user/config)
|
||||
- [非官方S3实现](user/custom)
|
||||
* 开发者手册
|
||||
- [开发计划](developers/plan)
|
||||
- [构建与运行](developers/building)
|
||||
- [代码结构](developers/framework)
|
||||
- [提交代码](developers/writing-code)
|
||||
- [编写文档](developers/writing-documents)
|
||||
- [贡献者列表](developers/contributors)
|
||||
* 核心机制
|
||||
- [上传](core/upload)
|
||||
- [下载](core/download)
|
||||
- [客户端直连](core/direct)
|
||||
- [缩略图](core/preview)
|
||||
- [桶策略](core/bucket)
|
||||
- [权限控制](core/auth)
|
||||
* 参考资料
|
||||
- [FAQ](references/faq)
|
||||
- [MinIO S3 接口](references/minio-s3-api)
|
||||
* MinIO 研究
|
||||
- [MinIO 分片 ETAG 生成机制](study/etag)
|
||||
- [Nginx 代理](study/proxy)
|
||||
@ -1 +0,0 @@
|
||||
# 常见问题
|
||||
@ -1,132 +0,0 @@
|
||||
# S3 API 兼容性列表
|
||||
|
||||
本页面列举了MinIO支持的亚马逊 S3 API 接口列表。
|
||||
|
||||
**MinIO 建议使用 [S3-Compatible SDK](https://min.io/docs/minio/linux/developers/minio-drivers.html#minio-drivers) 进行对象存储操作.**
|
||||
|
||||
## 对象API | Object APIs
|
||||
|
||||
* 创建已存储对象的副本 [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)
|
||||
* 删除对象 [DeleteObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObject.html)
|
||||
* 删除多个对象 [DeleteObjects](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html)
|
||||
* 删除对象标签 [DeleteObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjectTagging.html)
|
||||
* 获取对象 [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)
|
||||
* 获取对象属性 [GetObjectAttributes](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectAttributes.html)
|
||||
* 获取对象标签 [GetObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectTagging.html)
|
||||
* 获取对象Header信息 [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)
|
||||
* 返回存储桶中的(最多1000)对象 [ListObjects](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html)
|
||||
* 返回存储桶中的(最多1000)对象 V2 [ListObjectsV2](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html)
|
||||
* 返回存储桶中所有对象版本(包括当前版本和历史版本)的元数据 [ListObjectVersions](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html)
|
||||
* 将对象添加到存储桶中 [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
|
||||
* 将提供的标签集应用于存储桶中已存在的对象,标签是键值对。[PutObjectTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectTagging.html)
|
||||
* 恢复已存档的对象 [RestoreObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_RestoreObject.html)
|
||||
* 根据简化的SQL查询语句查询对象 [SelectObjectContent](https://docs.aws.amazon.com/AmazonS3/latest/API/API_SelectObjectContent.html)
|
||||
|
||||
### 对象锁 | Object Locking
|
||||
|
||||
* [GetObjectRetention](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectRetention.html)
|
||||
* [PutObjectRetention](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectRetention.html)
|
||||
* [GetObjectLegalHold](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLegalHold.html)
|
||||
* [PutObjectLegalHold](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLegalHold.html)
|
||||
* [GetObjectLockConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObjectLockConfiguration.html)
|
||||
* [PutObjectLockConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObjectLockConfiguration.html)
|
||||
|
||||
### 分片上传 | Multipart Uploads
|
||||
|
||||
* 终止分片上传任务并释放资源(该操作不确保一定释放资源) [AbortMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_AbortMultipartUpload.html)
|
||||
* 分片上传成功后合并分片 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
|
||||
* 创建分片上传任务并返回一个UploadId [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
|
||||
* 列出进行中(未完成或终止)的分片上传任务 [ListMultipartUploads](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListMultipartUploads.html)
|
||||
* 列出指定UploadId分片上传任务中已上传的分片 [ListParts](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListParts.html)
|
||||
* 上传分片文件 [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
|
||||
* 复制现有对象作为数据源来上传一个分片 [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
|
||||
|
||||
### 不支持的API | Unsupported API Object Endpoints
|
||||
|
||||
```
|
||||
GetObjectAcl
|
||||
PutObjectAcl
|
||||
```
|
||||
|
||||
## 桶API | Bucket APIs
|
||||
|
||||
* 创建存储桶 [CreateBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateBucket.html)
|
||||
* 删除存储桶 [DeleteBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucket.html)
|
||||
* 重置存储桶的加密方式为SSE-S3 [DeleteBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html)
|
||||
* 删除存储桶相关标签 [DeleteBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketTagging.html)
|
||||
* 获取存储桶的加密方式 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)
|
||||
* [GetBucketLocation](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html)
|
||||
* [GetBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketTagging.html)
|
||||
* [GetBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketVersioning.html)
|
||||
* [HeadBucket](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html)
|
||||
* [ListBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListBuckets.html)
|
||||
* [ListDirectoryBuckets](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListDirectoryBuckets.html)
|
||||
* [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)
|
||||
* [PutBucketTagging](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketTagging.html)
|
||||
* [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html)
|
||||
|
||||
### Bucket Replication
|
||||
|
||||
* [GetBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketReplication.html)
|
||||
* [PutBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketReplication.html)
|
||||
* [DeleteBucketReplication](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketReplication.html)
|
||||
|
||||
### 桶生命周期 | Bucket Lifecycle
|
||||
|
||||
* [GetBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycle.html)
|
||||
* [GetBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLifecycleConfiguration.html)
|
||||
* [PutBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycle.html)
|
||||
* [PutBucketLifecycleConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketLifecycleConfiguration.html)
|
||||
* [DeleteBucketLifecycle](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketLifecycle.html)
|
||||
|
||||
### Bucket Notifications
|
||||
|
||||
* [GetBucketNotification](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotification.html)
|
||||
* [GetBucketNotificationConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotificationConfiguration.html)
|
||||
* [PutBucketNotification](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotification.html)
|
||||
* [PutBucketNotificationConfiguration](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotificationConfiguration.html)
|
||||
|
||||
### Bucket Policies
|
||||
|
||||
* [GetBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicy.html)
|
||||
* [GetBucketPolicyStatus](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketPolicyStatus.html)
|
||||
* [PutBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketPolicy.html)
|
||||
* [DeleteBucketPolicy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html)
|
||||
|
||||
### 不支持的API | Unsupported API Bucket Endpoints
|
||||
|
||||
```
|
||||
GetBucketInventoryConfiguration
|
||||
PutBucketInventoryConfiguration
|
||||
DeleteBucketInventoryConfiguration
|
||||
PutBucketCors
|
||||
DeleteBucketCors
|
||||
GetBucketMetricsConfiguration
|
||||
PutBucketMetricsConfiguration
|
||||
DeleteBucketMetricsConfiguration
|
||||
PutBucketWebsite
|
||||
GetBucketLogging
|
||||
PutBucketLogging
|
||||
PutBucketAccelerateConfiguration
|
||||
DeleteBucketAccelerateConfiguration
|
||||
PutBucketRequestPayment
|
||||
DeleteBucketRequestPayment
|
||||
PutBucketAcl
|
||||
HeadBucketAcl
|
||||
GetPublicAccessBlock
|
||||
PutPublicAccessBlock
|
||||
DeletePublicAccessBlock
|
||||
GetBucketOwnershipControls
|
||||
PutBucketOwnershipControls
|
||||
DeleteBucketOwnershipControls
|
||||
GetBucketIntelligentTieringConfiguration
|
||||
PutBucketIntelligentTieringConfiguration
|
||||
ListBucketIntelligentTieringConfigurations
|
||||
DeleteBucketIntelligentTieringConfiguration
|
||||
GetBucketAnalyticsConfiguration
|
||||
PutBucketAnalyticsConfiguration
|
||||
ListBucketAnalyticsConfigurations
|
||||
DeleteBucketAnalyticsConfiguration
|
||||
CreateSession
|
||||
```
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
# 更新日志
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
# MinIO 分片 ETAG 生成机制
|
||||
|
||||
在 MinIO 中,分片上传和普通上传时,文件一致性校验是不一样的,我们分开说。
|
||||
|
||||
## 普通上传
|
||||
MinIO 会对所有上传的文件自动生成一个 Etag 标签,这个标签值的默认算法就是 MD5 。
|
||||
所以我们在做一致性校验时,前端程序读取本地文件进行 MD5 计算,在上传完成时,比较两个值是否一致即可校验一致性。
|
||||
|
||||
## 分片上传
|
||||
MinIO 会对每个分片进行 MD5 计算,每个分片有自己的 ETAG 标签,这个标签是隐藏的,只在 API 接口能查看,后台管理页面中是看不到的。
|
||||
在所有分片上传完成后,我们调用文件合并接口进行合并时,MinIO 会将全部所有分片的 ETAG 标签进行 byte[] 连接,然后计算这个 byte[] 的 MD5 值做为整个文件的 ETAG,而不会再次读取整个文件流来进行计算,这个文件的 ETAG 是可以在MinIO的后台管理界面中看到的。
|
||||
我们可以上传同一个文件到 MinIO 中,第一次使用普通上传、第二次分片上传,那么就会发现虽然是同一个文件,但是他们的 ETAG 值并不相同。
|
||||
|
||||
这里再提一个额外的知识,那就是 MinIO 在分片上传时会提前在磁盘创建出空洞文件(也可以叫稀疏文件),在合并文件时,并没有实际上的磁盘IO读写,所以合并分片是一个安全操作。
|
||||
那么在minio-plus中,为了保证性能,我们仅对分片的 MD5 计算结果也就是分片的 ETAG 值进行一致性比较,即可保证文件的整体一致性。
|
||||
|
||||
## 举个例子
|
||||
我现在上传一个18.9m的文件,按照5m进行分片,那么共计4个分片,如下图所示:
|
||||

|
||||
|
||||
可以看到文件的`ETAG`是`43abdc8a17419c3ac4400a7bb0d7d3b5-4`
|
||||
这个`ETAG`分成两部分,前面是MD5值,后面的分片数量。
|
||||
|
||||
那么现在我们模拟一下MinIO的`ETAG`计算过程,根据分片的`ETAG`计算整个文件的`ETAG`。
|
||||
```java
|
||||
String part1 = "101faaef4cc4567091dbf5c62d0f2a66";
|
||||
String part2 = "54b96a8a5cf6164c1e197ff9e97b9e3c";
|
||||
String part3 = "f647e6824a99b6ca06805dbc10756870";
|
||||
String part4 = "3c2f9b262e71c6fbf336432e9dbfe89b";
|
||||
|
||||
byte[] part1byte = HexUtil.decodeHex(part1) ;
|
||||
byte[] part2byte = HexUtil.decodeHex(part2) ;
|
||||
byte[] part3byte = HexUtil.decodeHex(part3) ;
|
||||
byte[] part4byte = HexUtil.decodeHex(part4) ;
|
||||
|
||||
byte[] result = new byte[part1byte.length + part2byte.length + part3byte.length + part4byte.length];
|
||||
|
||||
System.arraycopy(part1byte, 0, result, 0, part1byte.length);
|
||||
System.arraycopy(part2byte, 0, result, part1byte.length, part2byte.length);
|
||||
System.arraycopy(part3byte, 0, result, part1byte.length + part2byte.length, part3byte.length);
|
||||
System.arraycopy(part4byte, 0, result, part1byte.length + part2byte.length + part3byte.length, part4byte.length);
|
||||
|
||||
|
||||
System.out.println("直接字符串连接并计算MD5="+SecureUtil.md5(part1 + part2 + part3 + part4));
|
||||
|
||||
System.out.println("转义字节数组后拼接并计算MD5="+SecureUtil.md5(IoUtil.toStream(result)));
|
||||
```
|
||||
|
||||
运行截图:
|
||||

|
||||
|
||||
这里可以看到,直接进行字符串拼接是不行的,计算出的ETAG值与MinIO并不一致。
|
||||
而转换为字节数组后拼接,再计算,就一致了。
|
||||
@ -1 +0,0 @@
|
||||
# Nginx 代理
|
||||
@ -1,75 +0,0 @@
|
||||
# API接口
|
||||
|
||||
## 3.1 Service 层接口
|
||||
|
||||
提供文件上传、下载、删除等接口。
|
||||
|
||||
### 3.1.1 文件上传任务初始化
|
||||
|
||||
### 3.1.2 上传完成
|
||||
|
||||
### 3.1.3 取得文件下载地址
|
||||
|
||||
### 3.1.4 取得原图地址
|
||||
|
||||
### 3.1.5 取得缩略图地址
|
||||
|
||||
### 3.1.6 查询文件元数据
|
||||
|
||||
### 3.1.7 列表查询文件元数据
|
||||
|
||||
### 3.1.8 从字节数组创建文件
|
||||
|
||||
### 3.1.9 从输入流创建文件
|
||||
|
||||
### 3.1.10 从外部url创建文件
|
||||
|
||||
### 3.1.11 读取文件
|
||||
|
||||
### 3.1.12 删除文件
|
||||
|
||||
### 3.1.13 文件上传(MinIO原生接口)
|
||||
|
||||
### 3.1.14 文件下载(MinIO原生接口)
|
||||
|
||||
## 3.2 Controller 层接口
|
||||
|
||||
如没有特殊需求,也可以不写 Controller 层接口,minio-plus-extension 中提供了 Controller 层接口定义。
|
||||
|
||||
### 3.2.1 文件上传任务初始化
|
||||
|
||||
### 3.2.2 上传完成
|
||||
|
||||
### 3.2.3 文件下载
|
||||
|
||||
调用 3.1.3 取得文件下载地址后,返回前端时进行302跳转。
|
||||
|
||||
### 3.2.4 图片预览 - 原图
|
||||
|
||||
调用 3.1.3 取得原图地址后,返回前端时进行302跳转。
|
||||
|
||||
### 3.2.5 图片预览 - 缩略图
|
||||
|
||||
调用 3.1.3 取得缩略图地址后,返回前端时进行302跳转。
|
||||
|
||||
## 3.3 引用 MinIO 接口
|
||||
|
||||
这里给出本项目引用的 MinIO 接口列表。
|
||||
|
||||
### 3.3.1 bucketExists 检查文件桶是否存在
|
||||
|
||||
### 3.3.2 makeBucket 创建文件桶
|
||||
|
||||
### 3.3.3 createMultipartUpload 创建分片上传
|
||||
|
||||
### 3.3.4 completeMultipartUpload 合并文件
|
||||
|
||||
### 3.3.5 listParts 查询已上传的分片列表
|
||||
|
||||
### 3.3.6 getPresignedObjectUrl 获取上传、下载、预览图链接
|
||||
|
||||
### 3.3.7 putObject 上传
|
||||
|
||||
### 3.3.8 getObject 下载
|
||||
|
||||
### 3.3.9 removeObject 删除
|
||||
@ -1 +0,0 @@
|
||||
# 配置文件
|
||||
@ -1 +0,0 @@
|
||||
# 非官方S3实现
|
||||
@ -1,55 +0,0 @@
|
||||
# 文件元数据
|
||||
|
||||
文件元数据的数据结构设计,项目使用时,可自行扩展。
|
||||
|
||||
## 表设计
|
||||
|
||||
| Name | Type | Length | Not Null | Virtual | Key | Comment |
|
||||
|----------------|----------|--------|----------|---------|------|----------------|
|
||||
| id | bigint | 20 | True | False | True | 自增ID |
|
||||
| file_key | varchar | 50 | True | False | | 文件KEY |
|
||||
| file_md5 | varchar | 50 | False | False | | 文件MD5值 |
|
||||
| file_name | varchar | 255 | True | False | | 文件名 |
|
||||
| file_mime_type | varchar | 128 | False | False | | MIME类型 |
|
||||
| file_suffix | varchar | 20 | False | False | | 文件后缀 |
|
||||
| file_size | bigint | 20 | False | False | | 文件大小 |
|
||||
| is_preview | tinyint | 1 | False | False | | 预览图 0:无 1:有 |
|
||||
| is_private | tinyint | 1 | False | False | | 是否私有 0:否 1:是 |
|
||||
| bucket | varchar | 20 | True | False | | 存储桶 |
|
||||
| bucket_path | varchar | 20 | True | False | | 存储桶路径 |
|
||||
| upload_id | varchar | 255 | False | False | | 上传任务id |
|
||||
| is_finished | tinyint | 1 | True | False | | 状态 0:未完成 1:已完成 |
|
||||
| is_part | tinyint | 1 | False | False | | 是否分块 0:否 1:是 |
|
||||
| part_number | int | 4 | False | False | | 分块数量 |
|
||||
| create_time | datetime | | True | False | | 创建时间 |
|
||||
| create_user | varchar | 255 | True | False | | 创建用户 |
|
||||
| update_time | datetime | | True | False | | 更新时间 |
|
||||
| update_user | varchar | 255 | True | False | | 更新用户 |
|
||||
|
||||
## MySQL脚本
|
||||
```
|
||||
CREATE TABLE `file_metadata_info` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
`file_key` varchar(50) NOT NULL COMMENT '文件KEY',
|
||||
`file_md5` varchar(50) DEFAULT NULL COMMENT '文件md5',
|
||||
`file_name` varchar(255) NOT NULL COMMENT '文件名',
|
||||
`file_mime_type` varchar(128) DEFAULT NULL COMMENT 'MIME类型',
|
||||
`file_suffix` varchar(20) DEFAULT NULL COMMENT '文件后缀',
|
||||
`file_size` bigint(20) DEFAULT NULL COMMENT '文件大小',
|
||||
`is_preview` tinyint(1) DEFAULT '0' COMMENT '预览图 0:无 1:有',
|
||||
`is_private` tinyint(1) DEFAULT '0' COMMENT '是否私有 0:否 1:是',
|
||||
`bucket` varchar(20) NOT NULL COMMENT '存储桶',
|
||||
`bucket_path` varchar(20) NOT NULL COMMENT '存储桶路径',
|
||||
`upload_id` varchar(255) DEFAULT NULL COMMENT '上传任务id',
|
||||
`is_finished` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态 0:未完成 1:已完成',
|
||||
`is_part` tinyint(1) DEFAULT NULL COMMENT '是否分块 0:否 1:是',
|
||||
`part_number` int(4) DEFAULT NULL COMMENT '分块数量',
|
||||
`create_time` datetime NOT NULL COMMENT '创建时间',
|
||||
`create_user` varchar(255) NOT NULL COMMENT '创建用户',
|
||||
`update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
`update_user` varchar(255) NOT NULL COMMENT '更新用户',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
KEY `INDEX_KEY` (`file_key`),
|
||||
KEY `INDEX_MD5` (`file_md5`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文件元数据信息表';
|
||||
```
|
||||
@ -1,5 +0,0 @@
|
||||
# 快速开始
|
||||
|
||||
## 使用 minio-plus-all-spring-boot-starter
|
||||
|
||||
## 使用 minio-plus-core-spring-boot-starter
|
||||
@ -1,47 +0,0 @@
|
||||
---
|
||||
layout: home
|
||||
|
||||
title: MinIO-Plus
|
||||
titleTemplate: MinIO 的二次封装与增强工具
|
||||
|
||||
hero:
|
||||
name: MinIO-Plus
|
||||
text: 二次封装与增强工具
|
||||
tagline: 成为 MinIO 最好的搭档
|
||||
image:
|
||||
src: /logo.svg
|
||||
alt: MinIO-Plus
|
||||
actions:
|
||||
- theme: brand
|
||||
text: 快速开始
|
||||
link: /guide/user/quick-start
|
||||
- theme: alt
|
||||
text: 介绍
|
||||
link: /guide/intro
|
||||
- theme: alt
|
||||
text: 在Github上查看
|
||||
link: https://github.com/lxp135/minio-plus
|
||||
- theme: alt
|
||||
text: 在Gitee上查看
|
||||
link: https://gitee.com/lxp135/minio-plus
|
||||
|
||||
features:
|
||||
- icon: 🏹
|
||||
title: 文件秒传
|
||||
details: 对每个上传的文件进行哈希摘要识别,用户上传同一个文件时,没有文件实际传输过程,做到秒传。
|
||||
- icon: 📡
|
||||
title: 并发上传
|
||||
details: 将文件切分为小块。同时并发上传多个小块,最大限度地利用带宽,加快上传速度。
|
||||
- icon: ⛓
|
||||
title: 断点续传
|
||||
details: 在传输过程中遇到问题导致传输失败,只需重新传输未完成的小块,而不需要重新开始整个传输任务。
|
||||
- icon: 🗄️
|
||||
title: 缩略图生成
|
||||
details: 识别文件类型,在图片上传时自动生成缩略图,缩略图大小可配置。
|
||||
- icon: 🔑
|
||||
title: 访问权限控制
|
||||
details: 可支持基于用户、组的文件权限控制,保证重要文件的安全性。
|
||||
- icon: 🏁
|
||||
title: 客户端直连
|
||||
details: 前端直连 MinIO ,项目工程不做文件流的搬运,在支持以上特性的情况下提供 MinIO 原生性能。
|
||||
---
|
||||
@ -1,4 +0,0 @@
|
||||
<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg" fill="none" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m49.58378,29.95523c5.11126,-0.15399 10.21323,0.00046 15.30594,0.46382c-9.9535,17.04618 -19.84809,34.12992 -29.68424,51.2517c1.237,2.00972 2.47353,4.0199 3.71053,6.02961c27.05579,0.15445 54.11205,0.30937 81.16784,0.46382c-9.79858,16.89126 -19.53872,33.82055 -29.22042,50.78788c-12.52026,0.54127 -25.04329,0.61827 -37.56912,0.23191c-4.94753,-8.50314 -9.89459,-17.00675 -14.84212,-25.50989c5.10198,-0.30937 10.20396,-0.30937 15.30594,0c2.37752,3.90441 4.6966,7.84684 6.95724,11.82731c7.41642,0.54081 14.83748,0.61827 22.26318,0.23191c4.79261,-8.19424 9.58569,-16.38802 14.3783,-24.58226c-22.10873,-0.15445 -44.217,-0.30937 -66.32572,-0.46382c-3.76897,-6.3784 -7.4795,-12.79437 -11.13159,-19.24837c10.0175,-17.09812 19.9121,-34.25932 29.68424,-51.4836z" fill="#129dcb"/>
|
||||
<path d="m71.84696,29.95523c12.36952,-0.07746 24.73764,0 37.1053,0.23191c5.00597,8.54257 9.9535,17.12317 14.84212,25.7418c-5.10198,0.61827 -10.20396,0.61827 -15.30594,0c-2.31908,-4.0199 -4.63816,-8.03933 -6.95724,-12.05922c-7.42106,-0.61827 -14.84212,-0.61827 -22.26318,0c-4.63816,8.03933 -9.27633,16.07912 -13.91449,24.11845c21.95242,0.38636 43.90624,0.61827 65.86191,0.69572c3.76897,6.3784 7.4795,12.79437 11.13159,19.24837c-9.80229,17.14404 -19.69688,34.22778 -29.68424,51.2517c-5.10198,0.30937 -10.20396,0.30937 -15.30594,0c9.72159,-16.73681 19.38427,-33.51165 28.98852,-50.32406c0.30937,-0.61827 0.30937,-1.237 0,-1.85527c-0.9434,-1.48699 -1.79358,-3.03336 -2.55099,-4.63816c-27.21071,-0.30937 -54.42095,-0.61827 -81.63166,-0.92763c9.78281,-17.24979 19.67787,-34.41099 29.68424,-51.4836z" fill="#129dcb"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 258 KiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 179 KiB |
|
Before Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 185 KiB |
@ -1,4 +0,0 @@
|
||||
<svg viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m49.58378,29.95523c5.11126,-0.15399 10.21323,0.00046 15.30594,0.46382c-9.9535,17.04618 -19.84809,34.12992 -29.68424,51.2517c1.237,2.00972 2.47353,4.0199 3.71053,6.02961c27.05579,0.15445 54.11205,0.30937 81.16784,0.46382c-9.79858,16.89126 -19.53872,33.82055 -29.22042,50.78788c-12.52026,0.54127 -25.04329,0.61827 -37.56912,0.23191c-4.94753,-8.50314 -9.89459,-17.00675 -14.84212,-25.50989c5.10198,-0.30937 10.20396,-0.30937 15.30594,0c2.37752,3.90441 4.6966,7.84684 6.95724,11.82731c7.41642,0.54081 14.83748,0.61827 22.26318,0.23191c4.79261,-8.19424 9.58569,-16.38802 14.3783,-24.58226c-22.10873,-0.15445 -44.217,-0.30937 -66.32572,-0.46382c-3.76897,-6.3784 -7.4795,-12.79437 -11.13159,-19.24837c10.0175,-17.09812 19.9121,-34.25932 29.68424,-51.4836z" fill="none"/>
|
||||
<path d="m71.84696,29.95523c12.36952,-0.07746 24.73764,0 37.1053,0.23191c5.00597,8.54257 9.9535,17.12317 14.84212,25.7418c-5.10198,0.61827 -10.20396,0.61827 -15.30594,0c-2.31908,-4.0199 -4.63816,-8.03933 -6.95724,-12.05922c-7.42106,-0.61827 -14.84212,-0.61827 -22.26318,0c-4.63816,8.03933 -9.27633,16.07912 -13.91449,24.11845c21.95242,0.38636 43.90624,0.61827 65.86191,0.69572c3.76897,6.3784 7.4795,12.79437 11.13159,19.24837c-9.80229,17.14404 -19.69688,34.22778 -29.68424,51.2517c-5.10198,0.30937 -10.20396,0.30937 -15.30594,0c9.72159,-16.73681 19.38427,-33.51165 28.98852,-50.32406c0.30937,-0.61827 0.30937,-1.237 0,-1.85527c-0.9434,-1.48699 -1.79358,-3.03336 -2.55099,-4.63816c-27.21071,-0.30937 -54.42095,-0.61827 -81.63166,-0.92763c9.78281,-17.24979 19.67787,-34.41099 29.68424,-51.4836z" fill="none"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
@ -1,23 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"jsx": "preserve",
|
||||
"jsxImportSource": "vue",
|
||||
"lib": ["DOM", "ESNext"],
|
||||
"baseUrl": ".",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"types": ["vite/client", "node"],
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"noUnusedLocals": true,
|
||||
"outDir": "dist",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [".vitepress/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |