1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dromara-x-file-storage

28.02.2025 04:10
GitLife Service Account

Логотип
Исходное название X Spring File Storage теперь передано в dromara

x-file-storage.dromara.org | x-file-storage.xuyanwu.cn | spring-file-storage.xuyanwu.cn

github star star

📚 Описание

Один код для хранения файлов локально, FTP, SFTP, WebDAV, OSS Alibaba Cloud, OBS Huawei Cloud, KODO Qiniu Cloud, COS Tencent Cloud, BOS Baidu Cloud, USS Youzan Cloud, MinIO, Amazon S3, GoogleCloud Storage, FastDFS, Azure Blob Storage, Cloudflare R2, KS3 Kingsoft Cloud, MSS Meituan Cloud, OSS JD Cloud, OOS China Telecom Cloud, EOS Mobile Cloud, OSS WoYun, NOS NetEase, US3 UCloud, QingStor QingCloud, OBS PingAn Cloud, OSS FirstCloud, IBM COS и других платформ хранения, совместимых с протоколом S3. Посмотреть все поддерживаемые платформы хранения.

💡 Через WebDAV можно подключиться к Alist, чтобы использовать такие популярные службы хранения данных, как Бaidu Pan, Tianyi Yunpan, Aliyun Drive, Thunder Pan и другие. Посмотреть платформы хранения, поддерживаемые Alist

🚚 Поддерживает миграцию файлов между различными платформами хранения. Подробнее migrationBuilder.migration

GitHub: https://github.com/dromara/x-file-storage
Gitee: https://gitee.com/dromara/x-file-storage

Документация 1: https://x-file-storage.dromara.org
Документация 2: https://x-file-storage.xuyanwu.cn
Документация 3: https://spring-file-storage.xuyanwu.cn


📜 Обновление

  • Устранена проблема неправильного вычисления хэша в некоторых случаях
  • Устранена проблема использования предварительно подписанных URL в Qiniu Cloud KODO

📦 Использование

Нажмите быстрый старт для просмотра всех методов использования платформ хранения!

🔧 Настройка

Пример для Alibaba Cloud OSS. В pom.xml добавьте зависимость на этот проект. Здесь используется среда SpringBoot, но для других сред см. использование вне SpringBoot

<!-- Добавляем зависимость на этот проект -->
<dependency>
    <groupId>org.dromara.x-file-storage</groupId>
    <artifactId>x-file-storage-spring</artifactId>
    <version>2.2.1</version>
</dependency>
<!-- Добавляем зависимость на SDK Alibaba Cloud OSS, если используете другую платформу хранения, замените на соответствующее SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.16.1</version>
</dependency>

Добавьте следующие базовые конфигурации в файл application.yml

dromara:
  x-file-storage: # Конфигурация хранения файлов
    default-platform: aliyun-oss-1 # По умолчанию используемая платформа хранения
    aliyun-oss:
      - platform: aliyun-oss-1 # Идентификатор платформы хранения
        enable-storage: true  # Включение хранения
        access-key: ??
        secret-key: ??
        end-point: ??
        bucket-name: ??
        domain: ?? # Адрес доступа, обратите внимание на "/" в конце, например: https://abc.oss-cn-shanghai.aliyuncs.com/
        base-path: test/ # Базовый путь

🔨 Кодирование

Добавьте аннотацию @EnableFileStorage к запускающему классу.

@EnableFileStorage
@SpringBootApplication
public class SpringFileStorageTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringFileStorageTestApplication.class,args);
    }

}

✨ Начало загрузки

Поддерживается загрузка файлов типа File, MultipartFile, byte[], InputStream, URL, URI, String, HttpServletRequest. Для больших файлов автоматически выполняется разделение на части. Чтобы поддерживать больше способов загрузки, прочтите раздел о файлах.

@RestController
public class FileDetailController {

    @Autowired
    private FileStorageService fileStorageService; // Инъекция экземпляра

    /**
     * Загрузка файла
     */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
        // Только одна строчка кода для успешной загрузки
        return fileStorageService.of(file).upload();
    }
    
    /**
     * Загрузка файла, успешный ответ возвращает URL файла
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
                .setPath("upload/") // Сохраняет относительный путь, удобство управления, можно не указывать
                .setObjectId("0")   // ID связанного объекта, удобство управления, можно не указывать
                .setObjectType("0") // Тип связанного объекта, удобство управления, можно не указывать
                .putAttr("role","admin") // Сохраняет атрибуты, которые могут быть использованы в аспектах, записи загрузки, пользовательских платформах хранения и т.д., можно не указывать
                .upload();  // Загружает файл на указанное место
        return fileInfo == null ? "Загрузка не удалась!" : fileInfo.getUrl();
    }

    /**
     * Загрузка изображения, успешный ответ возвращает информацию о файле
     * Обработка изображений использует https://github.com/coobird/thumbnailator
     */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
        return fileStorageService.of(file)
                .image(img -> img.size(1000,1000))  // Изменяет размер изображения до 1000*1000
                .thumbnail(th -> th.size(200,200))  // Генерирует миниатюру размером 200*200
                .upload();
    }

    /**
     * Загрузка файла на конкретную платформу хранения, успешный ответ возвращает информацию о файле
     */
    @PostMapping("/upload-platform")
    public FileInfo uploadPlatform(MultipartFile file) {
        return fileStorageService.of(file)
                .setPlatform("aliyun-oss-1")    // Использует указанную платформу хранения
                .upload();
    }

    /**
     * Прямое чтение файла из HttpServletRequest и его загрузка, успешный ответ возвращает информацию о файле
     * При использовании этого подхода есть некоторые особенности, подробнее читайте в документации [основные возможности - загрузка](https://x-file-storage.xuyanwu.cn/#/%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
     */
    @PostMapping("/upload-request")
    public FileInfo uploadRequest(HttpServletRequest request) {
        return fileStorageService.of(request).upload();
    }
}

🎨 Другие операции

// Создание информации о файле вручную, может использоваться для других операций
FileInfo fileInfo = new FileInfo()
        .setPlatform("huawei-obs-1")
        .setBasePath("test/")
        .setPath("aa/")
        .setFilename("image.png")
        .setThFilename("image.png.min.jpg");

// Проверка наличия файла
boolean exists = fileStorageService.exists(fileInfo);
// Скачивание
byte[] bytes = fileStorageService.download(fileInfo).bytes();
// Удаление
fileStorageService.delete(fileInfo);
// Другие операции

Если сохранять запись загрузки в базе данных, то будет еще проще выполнять действия по URL. Подробнее читайте в разделе сохранение записи загрузки.

// Получение объекта FileInfo напрямую из базы данных, что делает выполнение других действий еще более простым
FileInfo fileInfo = fileStorageService.getFileInfoByUrl("https://abc.def.com/test/aa/image.png");
```// Проверка наличия файла
boolean exists = fileStorageService.exists("https://abc.def.com/test/aa/image.png");
// Скачивание
byte[] bytes = fileStorageService.download("https://abc.def.com/test/aa/image.png").bytes();
// Удаление
fileStorageService.delete("https://abc.def.com/test/aa/image.png");
// Другие операции

Нажмите быстрый старт для просмотра всех методов использования платформ хранения!

Последнее сообщение коммита: !49 Release 2.2.1
28.02.2025 04:08
GitLife Service Account

Логотип
Исходное название X Spring File Storage теперь передано в dromara открытый проект

x-file-storage.dromara.org | x-file-storage.xuyanwu.cn | spring-file-storage.xuyanwu.cn

github star star

📚 Описание

Один код для хранения файлов локально, FTP, SFTP, WebDAV, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Cloud Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youzan Cloud USS, MinIO,
Amazon S3, Google Cloud Storage, FastDFS, Azure Blob Storage, Cloudflare R2, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, China Telecom Cloud OOS, Mobile Cloud EOS, Unicom Cloud OSS, NetEase Digital Ocean NOS, UCloud US3, QingCloud QingStor, Ping An Cloud OBS, FirstCloud OSS, IBM COS, а также других платформ хранения, совместимых с протоколом S3. Посмотреть все поддерживаемые платформы хранения.

💡 Через WebDAV можно подключиться к Alist, после чего использовать такие популярные службы хранения данных как Baidu Pan, China Telecom Cloud Disk, Alibaba Cloud Drive, Thunder Network Disk и т.д., просмотреть поддерживаемые платформы Alist

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

GitHub: https://github.com/dromara/x-file-storage
Gitee: https://gitee.com/dromara/x-file-storage

Документация 1: https://x-file-storage.dromara.org
Документация 2: https://x-file-storage.xuyanwu.cn
Документация 3: https://spring-file-storage.xuyanwu.cn


📜 Обновление

  • Добавлено получение файла
  • Добавлено перечисление файлов
  • Переработана поддержка предварительно подписанных URL для клиентских операций загрузки, скачивания, удаления и т.д.
  • Добавлен плагин Solon
  • Обновлён версионный номер библиотеки Hutool
  • Улучшена работа с разделением больших файлов при загрузке, а также добавлена поддержка Google Cloud Storage
  • Улучшено обработание ошибок при создании миниатюр
  • Улучшена структура кода
  • Исправлено проблему с одинаковым значением хэша при работе с разделением файлов
  • Исправлены случайные ошибки при загрузке частей файлов в Minio
  • Исправлено отсутствие действия при добавлении статических ресурсов в локальное хранилище

📦 Использование

Нажмите быстрое начало работы для просмотра всех методов использования различных платформ хранения!

🔧 Настройка

Пример с использованием Alibaba Cloud OSS, pom.xml добавляет текущий проект, здесь используется среда Spring Boot, для других сред смотрите использование вне Spring Boot

<!-- Включение текущего проекта -->
<dependency>
    <groupId>org.dromara.x-file-storage</groupId>
    <artifactId>x-file-storage-spring</artifactId>
    <version>2.2.0</version>
</dependency>
<!-- Включение Alibaba Cloud OSS SDK, если используете другую платформу хранения, замените SDK соответственно -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.16.1</version>
</dependency>

Добавьте следующие базовые конфигурации в файл application.yml

dromara:
  x-file-storage: # Конфигурация хранения файлов
    default-platform: aliyun-oss-1 # По умолчанию используемая платформа хранения
    aliyun-oss:
      - platform: aliyun-oss-1 # Идентификатор платформы хранения
        enable-storage: true  # Включение хранения
        access-key: ??
        secret-key: ??
        end-point: ??
        bucket-name: ??
        domain: ?? # Адрес доступа, обратите внимание на завершение "/", например: https://abc.oss-cn-shanghai.aliyuncs.com/
        base-path: test/ # Базовый путь

🔨 Кодировка

Добавьте аннотацию @EnableFileStorage к запускающему классу

@EnableFileStorage
@SpringBootApplication
public class SpringFileStorageTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringFileStorageTestApplication.class,args);
    }

}

✨ Начало загрузки

Поддерживает File, MultipartFile, byte[], InputStream, URL, URI, String, HttpServletRequest, большие файлы автоматически разделяются на части при загрузке. Для поддержки большего количества способов загрузки, прочтите адаптеры файлов

@RestController
public class FileDetailController {

    @Autowired
    private FileStorageService fileStorageService; // Внедрение экземпляра

    /**
     * Загрузка файла
     */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
        // Только эта одна строчка кода необходима для успешной загрузки
        return fileStorageService.of(file).upload();
    }
    
    /**
     * Загрузка файла, успешный ответ возвращает URL файла
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
                .setPath("upload/") // Сохранение относительного пути, для удобства управления, можно не указывать
                .setObjectId("0")   // ID связанного объекта, для удобства управления, можно не указывать
                .setObjectType("0") // Тип связанного объекта, для удобства управления, можно не указывать
                .putAttr("role","admin") // Сохранение некоторых свойств, которые могут быть использованы в аспектах, записи загрузки, пользовательском хранении и т.д., можно не указывать
                .upload();  // Загрузка файла на указанное место
        return fileInfo == null ? "Загрузка неудачна!" : fileInfo.getUrl();
    }

    /**
     * Загрузка изображения, успешный ответ возвращает информацию о файле
     * Обработка изображений осуществляется через https://github.com/coobird/thumbnailator
     */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
        return fileStorageService.of(file)
                .image(img -> img.size(1000,1000))  // Изменение размера изображения до 1000*1000
                .thumbnail(th -> th.size(200,200))  // Создание миниатюры размером 200*200
                .upload();
    }

    /**
     * Загрузка файла на конкретную платформу хранения, успешный ответ возвращает информацию о файле
     */
    @PostMapping("/upload-platform")
    public FileInfo uploadPlatform(MultipartFile file) {
        return fileStorageService.of(file)
                .setPlatform("aliyun-oss-1")    // Использование конкретной платформы хранения
                .upload();
    }

    /**
     * Прямое чтение файла из HttpServletRequest и его загрузка, успешный ответ возвращает информацию о файле
     * При использовании этого подхода есть некоторые моменты внимания, читайте документацию [основные возможности - загрузка] секции
     */
    @PostMapping("/upload-request")
    public FileInfo uploadPlatform(HttpServletRequest request) {
        return fileStorageService.of(request).upload();
    }
}

🎨 Другие операции

//Ручное создание информации о файле, может быть использовано для других операций
FileInfo fileInfo = new FileInfo()
        .setPlatform("huawei-obs-1")
        .setBasePath("test/")
        .setPath("aa/")
        .setFilename("image.png")
        .setThFilename("image.png.min.jpg");
```// Существование файла
boolean exists = fileStorageService.exists(fileInfo);
// Загрузка
byte[] bytes = fileStorageService.download(fileInfo).bytes();
// Удаление
fileStorageService.delete(fileInfo);
// Другие более сложные операции



Если вы сохраняете запись загрузки в базе данных, то будет ещё проще выполнять операции по URL, подробнее [сохранение записи загрузки] секции

// Получение объекта FileInfo непосредственно из базы данных, что делает выполнение других операций ещё легче
FileInfo fileInfo = fileStorageService.getFileInfoByUrl("https://abc.def.com/test/aa/image.png");

// Существование файла
boolean exists = fileStorageService.exists("https://abc.def.com/test/aa/image.png");
// Загрузка
byte[] bytes = fileStorageService.download("https://abc.def.com/test/aa/image.png").bytes();
// Удаление
fileStorageService.delete("https://abc.def.com/test/aa/image.png");
// Другие более сложные операции

Нажмите быстрое начало работы для просмотра всех методов использования различных платформ хранения!

Последнее сообщение коммита: !48 Release 2.2.0
28.02.2025 04:05
GitLife Service Account

Логотип
Исходное название X Spring File Storage теперь передано в dromara открытый проект

x-file-storage.dromara.org | x-file-storage.xuyanwu.cn | spring-file-storage.xuyanwu.cn

github star star

📚 Описание

Один код для хранения файла локально, FTP, SFTP, WebDAV, OSS Alibaba Cloud, OBS Huawei Cloud, KODO Qiniu Cloud, COS Tencent Cloud, BOS Baidu Cloud, USS Youzan Cloud, MinIO, Amazon S3, GoogleCloud Storage, FastDFS, Azure Blob Storage, Cloudflare R2, KS3 Kingsoft Cloud, MSS Meituan Cloud, OSS JD Cloud, OOS China Telecom Cloud, EOS Mobile Cloud, OSS WoYun, NOS NetEase Digital Ocean, US3 UCloud, QingStor QingCloud, OBS PingAn Cloud, OSS FirstCloud, IBM COS и других платформ хранения, совместимых с протоколом S3. Посмотреть все поддерживаемые платформы хранения.

💡 Через WebDAV можно подключиться к Alist, используя сервисы хранения данных, такие как Бaidu Pan, Tianyi Yunpan, Aliyun Pan, Thunder Pan и другие популярные службы хранения данных. Посмотреть платформы хранения, поддерживаемые Alist

GitHub: https://github.com/dromara/x-file-storage
Gitee: https://gitee.com/dromara/x-file-storage

Документация 1: https://x-file-storage.dromara.org
Документация 2: https://x-file-storage.xuyanwu.cn
Документация 3: https://spring-file-storage.xuyanwu.cn


📜 Обновление

  • Добавлена платформа хранения FastDFS
  • Добавлена платформа хранения Azure Blob Storage
  • Добавлено копирование файлов, поддерживающее кросс-платформенные операции копирования
  • Добавлено перемещение (переименование) файлов, поддерживающее кросс-платформенные операции перемещения (переименования)
  • Добавлена возможность ручной разбиения больших файлов на части при загрузке (возможность возобновления загрузки)
  • Добавлена возможность вычисления хэша во время загрузки и скачивания
  • Удалено обязательное получение размера файла при загрузке, что делает загрузку файлов неизвестного размера более удобной
  • Улучшено автоматическое конфигурирование SpringBoot для совместимости с окружением без использования SpringWeb
  • Улучшено получение ключей файлов, чтобы избежать ошибок NullPointerException
  • Улучшен структурой кода загрузки
  • Улучшены обработчики исключений
  • Улучшены слушатели прогресса
  • Исправлен баг при установке имени файла миниатюры при загрузке
  • Совместимость с низкими версиями SpringBoot (2.0.x) для внедрения зависимостей
  • Исправлен баг отслеживания прогресса загрузки OBS Huawei Cloud
  • Исправлен баг закрытия входного потока при сохранении MultipartFile на локальном устройстве
  • Исправлен баг закрытия ответа при загрузке миниатюрного файла на USS Youzan Cloud

📦 Использование

Нажмите быстрое начало работы для просмотра всех методов использования всех платформ хранения!

🔧 Настройка

Пример с использованием OSS Alibaba Cloud, pom.xml добавляет этот проект, здесь используется среда SpringBoot, для других сред смотрите использование вне SpringBoot

<!-- Внедрение этого проекта -->
<dependency>
    <groupId>org.dromara.x-file-storage</groupId>
    <artifactId>x-file-storage-spring</artifactId>
    <version>2.1.0</version>
</dependency>
<!-- Внедрение OSS Alibaba Cloud SDK, если используется другая платформа хранения, то используйте соответствующий SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.16.1</version>
</dependency>

Добавьте следующие базовые настройки в файл конфигурации application.yml

dromara:
  x-file-storage: #Настройки хранения файлов
    default-platform: aliyun-oss-1 #По умолчанию используемая платформа хранения
    aliyun-oss:
      - platform: aliyun-oss-1 # Идентификатор платформы хранения
        enable-storage: true  # Активировать хранение
        access-key: ??
        secret-key: ??
        end-point: ??
        bucket-name: ??
        domain: ?? # Домен доступа, обратите внимание на завершение "/", например: https://abc.oss-cn-shanghai.aliyuncs.com/
        base-path: test/ # Базовый путь

🔨 Кодировка

Добавьте аннотацию @EnableFileStorage к запускающему классу

@EnableFileStorage
@SpringBootApplication
public class SpringFileStorageTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringFileStorageTestApplication.class,args);
    }

}

✨ Начало загрузки

Поддерживает File, MultipartFile, byte[], InputStream, URL, URI, String, HttpServletRequest, большие файлы будут автоматически разбиты на части при загрузке. Чтобы поддерживать больше способов, прочтите раздел адаптеры файлов

@RestController
public class FileDetailController {

    @Autowired
    private FileStorageService fileStorageService; // Внедрение экземпляра

    /**
     * Загрузка файла
     */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
        // Только эта одна строчка кода необходима для успешной загрузки
        return fileStorageService.of(file).upload();
    }
    
    /**
     * Загрузка файла, успешный ответ возвращает URL файла
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
                .setPath("upload/") // Сохранение относительного пути, для удобства управления, можно не указывать
                .setObjectId("0")   // ID связанного объекта, для удобства управления, можно не указывать
                .setObjectType("0") // Тип связанного объекта, для удобства управления, можно не указывать
                .putAttr("role","admin") // Сохранение некоторых атрибутов, которые могут быть использованы в аспектах, записи загрузки, пользовательских платформах хранения и т.д., можно не указывать
                .upload();  // Загрузка файла на указанное место
        return fileInfo == null ? "Загрузка не удалась!" : fileInfo.getUrl();
    }

    /**
     * Загрузка изображения, успешный ответ возвращает информацию о файле
     * Обработка изображений использует https://github.com/coobird/thumbnailator
     */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
        return fileStorageService.of(file)
                .image(img -> img.size(1000,1000))  // Изменение размера изображения до 1000*1000
                .thumbnail(th -> th.size(200,200))  // Создание миниатюры размером 200*200
                .upload();
    }

    /**
     * Загрузка файла на указанную платформу хранения, успешный ответ возвращает информацию о файле
     */
    @PostMapping("/upload-platform")
    public FileInfo uploadPlatform(MultipartFile file) {
        return fileStorageService.of(file)
                .setPlatform("aliyun-oss-1")    // Использование указанной платформы хранения
                .upload();
    }
}```java
/**
 * Прямое чтение файла из HttpServletRequest для загрузки, успешный ответ возвращает информацию о файле.
 * При использовании этого подхода есть некоторые моменты внимания, подробнее читайте в документации раздела [основные возможности — загрузка](https://x-file-storage.xuyanwu.cn/#/%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%B0)
 */
@PostMapping("/upload-request")
public FileInfo uploadPlatform(HttpServletRequest request) {
    return fileStorageService.of(request).upload();
}

🎨 Другие действия

//Ручное создание информации о файле, может быть использовано для других действий
FileInfo fileInfo = new FileInfo()
        .setPlatform("huawei-obs-1")
        .setBasePath("test/")
        .setPath("aa/")
        .setFilename("image.png")
        .setThumbFilename("image.png.min.jpg");

//Проверка наличия файла
boolean exists = fileStorageService.exists(fileInfo);
//Загрузка файла
byte[] bytes = fileStorageService.download(fileInfo).bytes();
//Удаление файла
fileStorageService.delete(fileInfo);
//Другие действия

Если запись о загруженном файле сохранена в базе данных, это позволит ещё легче работать с файлами по URL, подробнее читайте в разделе сохранение записи загрузки

//Прямое получение FileInfo объекта из базы данных, что позволяет легко выполнять другие действия
FileInfo fileInfo = fileStorageService.getFileInfoByUrl("https://abc.def.com/test/aa/image.png");

//Проверка наличия файла
boolean exists = fileStorageService.exists("https://abc.def.com/test/aa/image.png");
//Загрузка файла
byte[] bytes = fileStorageService.download("https://abc.def.com/test/aa/image.png").bytes();
//Удаление файла
fileStorageService.delete("https://abc.def.com/test/aa/image.png");
//Другие действия

Нажмите быстрое начало работы для просмотра всех методов использования всех платформ хранения!

Последнее сообщение коммита: !36 Fix README.md
28.02.2025 04:02
GitLife Service Account

Логотип
Исходное название X Spring File Storage теперь передано в dromara открытый проект

x-file-storage.dromara.org | x-file-storage.xuyanwu.cn | spring-file-storage.xuyanwu.cn

github star star

📚Описание

Один код для хранения файлов локально, FTP, SFTP, WebDAV, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Cloud Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youku Cloud USS, MinIO,
Amazon S3, Google Cloud Storage, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, China Telecom Cloud OOS, China Mobile EOS, Unicom OSS,
NetEase Digital Sail NOS, UCloud US3, QingCloud QingStor, Ping An Cloud OBS, FirstCloud OSS, IBM COS, других платформ с совместимостью протокола S3. Посмотреть все поддерживаемые платформы

💡 Через WebDAV можно подключиться к Alist, после чего можно использовать такие популярные сервисы хранения данных как Baidu Netdisk, China Telecom Cloud Disk, Alibaba Cloud Disk, Thunder Netdisk и т.д., подробнее поддержка Alist

GitHub: https://github.com/dromara/x-file-storage
Gitee: https://gitee.com/dromara/x-file-storage

Документация 1: https://x-file-storage.dromara.org
Документация 2: https://x-file-storage.xuyanwu.cn
Документация 3: https://spring-file-storage.xuyanwu.cn


📜Обновление

  • Изменение названия проекта, пакета, оптимизация структуры проекта
  • Добавлено прямое чтение потока HttpServletRequest для загрузки, файлы не записываются на диск, что увеличивает скорость
  • Поддержка метаданных Metadata
  • Оптимизация обработки ошибок ACL
  • Улучшение логики удаления файлов
  • Временные проблемы при загрузке файла на Amazon S3 исправлены
  • Передано в dromara сообщество open source

Изменение зависимостей проекта

2.0.0 и более ранние версии

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>1.0.3</version>
</dependency>

2.0.0 и более новые версии

<dependency>
    <groupId>org.dromara.x-file-storage</groupId>
    <artifactId>x-file-storage-spring</artifactId>
    <version>2.0.0</version>
</dependency>

Изменение конфигурационных параметров

2.0.0 и более ранние версии

spring:
  file-storage: #конфигурация хранения файлов
    default-platform: huawei-obs-1 #по умолчанию используемая платформа хранения
    thumbnail-suffix: ".min.jpg" #суффикс миниатюр, например [.min.jpg][.png]
    #конфигурация соответствующей платформы здесь, обратите внимание на отступы

2.0.0 и более новые версии

dromara:
  x-file-storage: #конфигурация хранения файлов
    default-platform: huawei-obs-1 #по умолчанию используемая платформа хранения
    thumbnail-suffix: ".min.jpg" #суффикс миниатюр, например [.min.jpg][.png]
    #конфигурация соответствующей платформы здесь, обратите внимание на отступы

Изменение пакетов

2.0.0 и более ранние версии

cn.xuyanwu.spring.file.storage
cn.xuyanwu.spring.file.storage.spring

2.0.0 и более новые версии

org.dromara.x.file.storage.core
org.dromara.x.file.storage.spring

📦Использование

Нажмите быстрый старт для просмотра всех методов использования всех платформ!

🔧 Конфигурация

Пример с использованием Aliyun OSS, pom.xml добавляет этот проект, здесь используется SpringBoot, для других сред смотрите использование вне SpringBoot

<!-- Добавляем текущий проект -->
<dependency>
    <groupId>org.dromara.x-file-storage</groupId>
    <artifactId>x-file-storage-spring</artifactId>
    <version>2.0.0</version>
</dependency>
<!-- Добавляем библиотеку SDK Aliyun OSS, если вы используете другую платформу хранения, то добавьте соответствующую библиотеку SDK -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.16.1</version>
</dependency>

Добавьте следующие базовые конфигурации в файл application.yml

dromara:
  x-file-storage: #конфигурация хранения файлов
    default-platform: aliyun-oss-1 #по умолчанию используемая платформа хранения
    aliyun-oss:
      - platform: aliyun-oss-1 #идентификатор платформы хранения
        enable-storage: true  #включение хранения
        access-key: ??
        secret-key: ??
        end-point: ??
        bucket-name: ??
        domain: ?? #домен доступа, обратите внимание на завершающий "/", например: https://abc.oss-cn-shanghai.aliyuncs.com/
        base-path: test/ #базовый путь

🔨 Кодирование

Добавьте аннотацию @EnableFileStorage к запускающему классу

@EnableFileStorage
@SpringBootApplication
public class SpringFileStorageTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringFileStorageTestApplication.class, args);
    }

}

✨ Загрузка файлов

Поддерживает File, MultipartFile, byte[], InputStream, URL, URI, String, HttpServletRequest, большие файлы автоматически разбиваются на части для загрузки. Чтобы поддерживать больше способов, прочитайте раздел адаптеры файлов.

@RestController
public class FileDetailController {

    @Autowired
    private FileStorageService fileStorageService; //инжектирование экземпляра

    /**
     * Загрузка файла
     */
    @PostMapping("/upload")
    public FileInfo upload(MultipartFile file) {
        //только эта одна строчка кода необходима для успешной загрузки
        return fileStorageService.of(file).upload();
    }
    
    /**
     * Загрузка файла, успешный ответ возвращает URL файла
     */
    @PostMapping("/upload2")
    public String upload2(MultipartFile file) {
        FileInfo fileInfo = fileStorageService.of(file)
                .setPath("upload/") //сохраняет относительный путь, чтобы было удобнее управлять, если не требуется, можно не указывать
                .setObjectId("0")   //ассоциированный объект ID, чтобы было удобнее управлять, если не требуется, можно не указывать
                .setObjectType("0") //тип ассоциированного объекта, чтобы было удобнее управлять, если не требуется, можно не указывать
                .putAttr("role","admin") //сохраняет некоторые атрибуты, которые могут быть получены и использованы в аспектах, записи загрузки, пользовательских платформах хранения и т.д., если не требуется, можно не указывать
                .upload();  //загружает файл на соответствующее место
        return fileInfo == null ? "Загрузка неудачна!" : fileInfo.getUrl();
    }

    /**
     * Загрузка изображения, успешный ответ возвращает информацию о файле
     * Обработка изображений использует https://github.com/coobird/thumbnailator
     */
    @PostMapping("/upload-image")
    public FileInfo uploadImage(MultipartFile file) {
        return fileStorageService.of(file)
                .image(img -> img.size(1000,1000))  //устанавливает размер изображения до 1000*1000
                .thumbnail(th -> th.size(200,200))  //генерирует миниатюру размером 200*200
                .upload();
    }
}```java
/**
 * Загрузка файла на указанную платформу хранения, успешный ответ возвращает информацию о файле
 */
@PostMapping("/upload-platform")
public FileInfo uploadPlatform(@RequestParam MultipartFile file) {
    return fileStorageService.of(file)
            .setPlatform("aliyun-oss-1")    // использует указанную платформу хранения
            .upload();
}

/**
 * Прямое чтение файла из HttpServletRequest для загрузки, успешный ответ возвращает информацию о файле
 * При использовании этого подхода есть несколько моментов, которые следует учесть, подробнее читайте в документации разделе [основные возможности - загрузка](https://x-file-storage.xuyanwu.cn/#/%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)
 */
@PostMapping("/upload-request")
public FileInfo uploadRequest(HttpServletRequest request) {
    return fileStorageService.of(request).upload();
}

Другие операции

// Ручное создание информации о файле, может быть использовано для других операций
FileInfo fileInfo = new FileInfo()
        .setPlatform("huawei-obs-1")
        .setBasePath("test/")
        .setPath("aa/")
        .setFilename("image.png")
        .setThumbFilename("image.png.min.jpg");

// Существование файла
boolean exists = fileStorageService.exists(fileInfo);
// Загрузка
byte[] bytes = fileStorageService.download(fileInfo).getBytes();
// Удаление
fileStorageService.delete(fileInfo);
// Другие операции

Если сохранять записи загрузки в базе данных, это позволит ещё легче управлять файлами по URL, подробнее читайте в разделе запись загрузки

// Получение объекта FileInfo напрямую из базы данных, что делает выполнение других операций ещё проще
FileInfo fileInfo = fileStorageService.getFileInfoByUrl("https://abc.def.com/test/aa/image.png");

// Существование файла
boolean exists = fileStorageService.exists("https://abc.def.com/test/aa/image.png");
// Загрузка
byte[] bytes = fileStorageService.download("https://abc.def.com/test/aa/image.png").getBytes();
// Удаление
fileStorageService.delete("https://abc.def.com/test/aa/image.png");
// Другие операции

Нажмите быстрый старт для просмотра всех методов использования всех платформ!

Последнее сообщение коммита: !30 Release 2.0.0
28.02.2025 03:52
GitLife Service Account
  • Исправлена проблема с автоматической загрузкой в FileStorageClientFactory
  • Оптимизирован способ преобразования ACL в HuaweiObsFileStorage для совместимости с низкими версиями SDK
  • Исправлено возникновение пустых указателей при преобразовании ACL в GoogleCloudStorageFileStorage
  • Исправлены проблемы отображения ошибок в Youpai Cloud USS

Эта версия поддерживает локальное хранение, FTP, SFTP, WebDAV, облачное хранилище Google, OSS Alibaba Cloud, OBS Huawei Cloud, KODO Qiniu Cloud, COS Tencent Cloud, BOS Baidu Cloud, USS Youpai Cloud, MinIO, AWS S3, KS3 Kingsoft Cloud, MSS Meituan Cloud, OSS JD Cloud, OOS China Telecom Cloud, EOS China Mobile Cloud, OSS Unicom Cloud, NOS NetEase Cloudbase, US3 UCloud, QingStor QCloud, OBS PingAn Cloud, OSS FirstCloud, IBM COS и другие платформы, совместимые со стандартом S3.

Рекомендуется использовать через Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>1.0.3</version>
</dependency>

Чтобы начать использование, прочитайте документацию!

Последнее сообщение коммита: !26 Release 1.0.3
28.02.2025 03:51
GitLife Service Account
  • Устранена проблема с незагрузкой Huawei Cloud OBS

Этот выпуск поддерживает локальные, FTP, SFTP, WebDAV, Google Cloud Storage, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Cloud Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youku Cloud USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, Telecom Cloud OOS, China Mobile EOS, Unicom Cloud OSS, NetEase Cloud Base NOS, UCloud US3, QingCloud QingStor, PingAn Cloud OBS, FirstCloud OSS, IBM Cloud Object Storage и другие платформы, совместимые со S3 протоколом.

Рекомендуется использовать через Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>1.0.2</version>
</dependency>

Чтобы начать работу, прочитайте документацию!

Последнее сообщение коммита: !25 Release 1.0.2
28.02.2025 03:51
GitLife Service Account
  • Исправлено проблемное поведение MultipartFileWrapperAdapter, связанное с неправильным получением имени файла.
  • Устранена проблема отсутствия метаданных конфигурационных файлов.

Эта версия поддерживает локальное хранение, FTP, SFTP, WebDAV, Google Cloud Storage, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youku USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, Telecom Cloud OOS, China Mobile EOS, Unicom Cloud OSS, NetEase Yanwu NOS, UCloud US3, QingCloud QingStor, PingAn Cloud OBS, FirstCloud OSS, IBM Cloud Object Storage и другие платформы, совместимые со стандартом S3.

Рекомендуется использовать библиотеку через Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>1.0.1</version>
</dependency>

Чтобы начать использование, ознакомьтесь с документацией!

Последнее сообщение коммита: !24 Release 1.0.1
28.02.2025 03:51
GitLife Service Account

Этот выпуск включает значительные изменения и множество новых возможностей; при переходе с предыдущих версий следует провести полное тестирование!

  • В конфигурационных файлах имя Amazon S3 хранилища было изменено с aws-s3 на amazon-s3.
  • В конфигурационных файлах имя Google Cloud Storage хранилища было изменено с google-cloud на google-cloud-storage.
  • В интерфейсе записи файлов (FileRecorder) метод record был заменён на save.
  • Программа теперь может работать независимо от Spring Boot (что удобнее для интеграции с другими системами).
  • Поддержка загрузки больших файлов.
  • Отслеживание прогресса загрузки.
  • Добавлен клиентский интерфейс фабрик для платформ хранения, что позволяет использовать сетевые прокси, а также инициализировать объекты клиента через STS.
  • Поддержка управления доступом на уровне объекта (ACL) для облачных хранилищ.
  • Возможность получения временных ссылок для доступа к объектам (предварительно подписанных URL).
  • Устранение проблемы использования всего содержимого файла в памяти во время загрузки, что снижает потребление оперативной памяти.
  • Оптимизация производительности работы с FTP и SFTP за счет использования пула объектов Apache.
  • Исправлена совместимость с WebDAV; прошла проверку совместимость с XiaoMi Yun, NextCloud; теоретически поддерживается большинство других платформ, можно самостоятельно протестировать.
  • Исправлены некоторые проблемы с использованием локального хранилища в некоторых версиях Spring Boot.
  • Метод getClient в платформах хранения теперь заблокирован для решения проблем повторной инициализации при параллельном выполнении.
  • Реализован вызов специальных методов хранилищ через рефлексию, что делает использование уникальных методов различных хранилищ более простым.
  • Добавлен интерфейс адаптера файлов, позволяющий создавать собственные адаптеры для различных типов ресурсов.
  • Общий архитектурный дизайн был улучшен для повышения удобства использования.

Поддерживаются следующие платформы хранения: локальное хранилище, FTP, SFTP, WebDAV, Google Cloud Storage, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youku USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, China Telecom OOS, China Mobile EOS, Unicom OSS, NetEase NOS, UCloud US3, QingCloud QingStor, Ping An Cloud OBS, ShouYun Cloud OSS, IBM Cloud COS и другие, поддерживающие протокол S3.

Рекомендация по внедрению:

<dependency>
    <groupId>cn.xuyanwu</groupId>
   <artifactId>spring-file-storage</artifactId>
    <version>1.0.0</version>
</dependency>

Чтобы начать работу, прочитайте документацию!

Последнее сообщение коммита: !23 Fix README.md
28.02.2025 03:50
GitLife Service Account
  • Добавлена поддержка Google Cloud Storage, предоставленной kytrun, большое спасибо
  • Исправлено некорректное сообщение об ошибке в WebDAV
  • Используется Tika для распознавания типа контента

Этот выпуск поддерживает локальные хранилища, FTP, SFTP, WebDAV, Google Cloud Storage, Alibaba Cloud OSS, Huawei Cloud OBS, Qiniu Kodo, Tencent Cloud COS, Baidu Cloud BOS, Upyun USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, Telecom Cloud OOS, China Mobile Cloud EOS, Unicom Cloud OSS, NetEase Clouder NOS, UCloud US3, QingCloud QingStor, PingAn Cloud OBS, FirstCloud OSS, IBM Cloud Object Storage и другие платформы, совместимые с протоколом S3.

Рекомендуется использовать Maven для внедрения зависимости:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.7.0</version>
</dependency>

Чтобы начать работу, прочитайте документацию!

Последнее сообщение коммита: !16 update:文档
28.02.2025 03:50
GitLife Service Account
  • Улучшить способ идентификации ContentType

Эта версия поддерживает локальные, FTP, SFTP, WebDAV, облачное хранилище Alibaba Cloud OSS, Huawei Cloud OBS, KODO Qiniu Cloud, Tencent Cloud COS, Baidu Cloud BOS, Youku Cloud USS, MinIO, AWS S3, облачное хранилище Kingsoft Cloud KS3, облачное хранилище Meituan Cloud MSS, облачное хранилище JD Cloud OSS, облачное хранилище Telecom Cloud OOS, облачное хранилище China Mobile Cloud EOS, облачное хранилище Unicom Cloud OSS, облачное хранилище NetEase Clouder NOS, облачное хранилище UCloud US3, облачное хранилище QingCloud QingStor, облачное хранилище PingAn Cloud OBS, облачное хранилище FirstCloud OSS, облачное хранилище IBM Cloud Object Storage и другие платформы, совместимые с протоколом S3.

Рекомендуется использовать зависимость Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.6.1</version>
</dependency>

Прочтите документацию и начните использование!

Последнее сообщение коммита: !11 Release 0.6.1
28.02.2025 03:49
GitLife Service Account
  • Добавлена поддержка FTP, SFTP, WebDAV
  • Улучшено локальное хранилище LocalPlusFileStorage; рекомендовано для новых проектов, а старым проектам следует продолжать использовать LocalFileStorage для обеспечения совместимости
  • Оптимизировано использование облачного хранилища Youku USS
  • Улучшено использование облачного хранилища Qiniu KODO

Этот выпуск поддерживает следующие типы хранилищ: локальные, FTP, SFTP, WebDAV, облачное хранилище Alibaba Cloud OSS, облачное хранилище Huawei Cloud OBS, облачное хранилище Qiniu KODO, облачное хранилище Tencent Cloud COS, облачное хранилище Baidu Cloud BOS, облачное хранилище Youku USS, MinIO, облачное хранилище AWS S3, облачное хранилище Kingsoft Cloud KS3, облачное хранилище Meituan Cloud MSS, облачное хранилище JD Cloud OSS, облачное хранилище China Telecom Cloud OOS, облачное хранилище China Mobile Cloud EOS, облачное хранилище Unicom Cloud OSS, облачное хранилище NetEase Wangshang NOS, облачное хранилище UCloud US3, облачное хранилище QingCloud QingStor, облачное хранилище PingAn Cloud OBS, облачное хранилище FirstCloud OSS, облачное хранилище IBM Cloud Object Storage и другие платформы, поддерживающие протокол S3.

Рекомендуется использовать Maven для включения зависимости:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.6.0</version>
</dependency>

Чтобы начать работу, прочитайте документацию!

Последнее сообщение коммита: !10 0.6.0
28.02.2025 03:49
GitLife Service Account
  • Добавлена поддержка ContentType и ContentLength
  • Добавлен атрибут FileInfo: attr, это словарный объект, который позволяет более удобно связывать данные
  • Изменено свойство id в FileInfo с Integer на String, что делает его более универсальным
  • Прочие оптимизации производительности
  • Обновлены зависимости

Эта версия поддерживает локальное хранение, Aliyun OSS, Huawei Cloud OBS, Qiniu Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youzan USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, Telecom Cloud OOS, China Mobile EOS, Unicom Cloud OSS, NetEase Cloudbase NOS, UCloud US3, QingCloud QingStor, PingAn Cloud OBS, ShuYun OSS, IBM COS и другие платформы, совместимые со S3 протоколом.

Рекомендуется использовать через Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.5.0</version>
</dependency>

Чтобы начать использование, прочитайте документацию!

Последнее сообщение коммита: !8 0.5.0
28.02.2025 03:48
GitLife Service Account

Добавлена поддержка AWS S3

Эта версия поддерживает локальное хранение, Aliyun OSS, Huawei Cloud OBS, Qiniu Kodo, Tencent Cloud COS, Baidu Cloud BOS, Youku USS, MinIO, AWS S3, Kingsoft Cloud KS3, Meituan Cloud MSS, JD Cloud OSS, Telecom Cloud OOS, China Mobile EOS, Unicom Cloud OSS, NetEase Cloudbase NOS, UCloud US3, QingCloud QingStor, PingAn Cloud OBS, FirstCloud OSS, IBM Cloud Object Storage и другие платформы, совместимые с протоколом S3.

Рекомендуется использовать зависимость через Maven:

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.4.0</version>
</dependency>

Чтобы начать работу, ознакомьтесь с документацией!

Последнее сообщение коммита: !5 Release 0.4.0
28.02.2025 03:48
GitLife Service Account
  • Добавлена официальная документация
  • Добавлена возможность отслеживания прогресса загрузки
  • Добавлена поддержка динамического добавления/удаления хранилищ данных и аспектов
  • Добавлен метод: перегруженный метод для прямого определения существования файла
  • Устранено ошибочное определение завершения загрузки в мониторинге прогресса загрузки

Эта версия поддерживает локальное хранение, Aliyun OSS, Huawei OBS, Qiniu Kodo, Tencent COS, Baidu BOS, Youku USS, MinIO

Рекомендуется использовать Maven для внедрения

<dependency>
    <groupId>cn.xuyanwu</groupId>
   <artifactId>spring-file-storage</artifactId>
    <version>0.3.0</version>
</dependency>
Последнее сообщение коммита: !3 Release 0.3.0
28.02.2025 03:48
GitLife Service Account

Исправление проблемы с хранением локального пути thUrl, содержащего basePath

Эта версия поддерживает локальное хранилище, Aliyun OSS, Huawei OBS, Qiniu Kodo, Tencent COS, Baidu BOS, UpYun USS, MinIO

Рекомендуется использовать Maven для включения зависимости

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.2.1</version>
</dependency>
Последнее сообщение коммита: Merge pull request #19 from 1171736840/dev
28.02.2025 03:48
GitLife Service Account

Оптимизация процесса автоматической конфигурации
Добавление поддержки MinIO
Исправление ошибок в названиях переменных

Эта версия поддерживает локальное хранение, Aliyun OSS, Huawei OBS, Qiniu Kodo, Tencent COS, Baidu BOS, Youku USS, MinIO

Рекомендуется использовать Maven для включения зависимости

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.2.0</version>
</dependency>
Последнее сообщение коммита: Merge pull request #17 from 1171736840/dev
28.02.2025 03:48
GitLife Service Account

Поддержка локального хранения, Aliyun OSS, Huawei OBS, Qiniu Kodo, Tencent COS, Baidu BOS, UpYun USS

Рекомендуется использовать Maven для включения зависимости

<dependency>
    <groupId>cn.xuyanwu</groupId>
    <artifactId>spring-file-storage</artifactId>
    <version>0.1.6</version>
</dependency>
Последнее сообщение коммита: Merge pull request #14 from 1171736840/dev
1
https://api.gitlife.ru/oschina-mirror/dromara-x-file-storage.git
git@api.gitlife.ru:oschina-mirror/dromara-x-file-storage.git
oschina-mirror
dromara-x-file-storage
dromara-x-file-storage