SpringBoot + Minio реализует чрезвычайно быструю технологию загрузки файлов (Practical Collection Edition).
SpringBoot + Minio реализует чрезвычайно быструю технологию загрузки файлов (Practical Collection Edition).

Привет всем, я Букай Чен~

1. Обзор

Совет: не переключайтесь между несколькими блогами. Эта статья уникальна и сочетает в себе сильные стороны многих блогов. Если вы столкнулись с ошибкой, внимательно прочитайте статью и не игнорируйте ее. Когда я писал, поскольку многие статьи не были исчерпывающими, я столкнулся со многими ловушками, прыгая взад и вперед. Надеюсь, вы сможете их избежать, я отметил их все в этой статье, чтобы напомнить вам! ! !

Официальный адрес сайта:

https://min.io/

Адрес документа:

https://docs.min.io/

Адрес исходного кода этого документа (бесплатный ресурс):

https://download.csdn.net/download/weixin_53742691/87856930

Minio — это сервер объектного хранилища с открытым исходным кодом, который может работать в различных операционных системах, включая Linux, Windows и MacOS. Он предоставляет простое, масштабируемое и высокодоступное решение для хранения объектов, поддерживающее несколько форматов данных, включая объекты, блоки и файлы.

Вот основные особенности Minio:

  • Простой и удобный в использовании: Установка Minio очень проста, вам просто нужно скачать и запустить соответствующий бинарный файл. Он предоставляет веб-сайт UI, вы можете управлять стволом хранилища и объектами через интерфейс.
  • Масштабируемость: Minio можно легко расширить до нескольких узлов,Обеспечить высокую доступность и отказоустойчивость. Он поддерживает несколько режимов развертывания.,В том числе одиночный узел, копирование кластера master-slave и т. д.
  • Высокая доступность: Minio предоставляет различные механизмы для обеспечения надежности и доступности данных, включая избыточное резервное копирование, копирование данных при сбое и т. д.
  • Безопасность: Minio предоставляет различные механизмы безопасности для защиты конфиденциальности и целостности данных, включая шифрование SSL/TLS, контроль доступа, шифрование данных и т. д.
  • Многоязычная поддержка: Minio поддерживает несколько языков программирования, включая Java, Python, Ruby и Go и т. д.
  • Поддержка сообщества: Minio — это проект с открытым исходным кодом, имеющий огромную поддержку сообщества и участников. Его исходный код доступен на GitHub, существует активный список рассылки и форум.
  • объектхранилище: Основная функциональность Minio — это объектхранилище. Он позволяет пользователям загружать и загружать объекты любого количества и размера и предоставляет различные API и SDK для доступа к этим объектам.
  • Хранение: Minio также поддерживает хранилище.,Разрешить пользователям загружатьи Скачать большойдокумент(например изображения или видео)。кусокхранилищеэто быстрый、Эффективный способ справиться с большимидокумент。
  • документхранилище: Minio также поддерживает хранение документов.,Разрешить пользователям загружатьи Скачать синглдокумент。документхранилищеэто простой、Быстрый способ справиться с небольшимдокумент。

Короче говоря, Minio — это мощный, гибкий и масштабируемый сервер объектного хранения, подходящий для различных сценариев применения, включая облачное хранилище, хранилище больших данных и Интернет вещей.

2. Сценарии применения

MinIO — это высокопроизводительная масштабируемая объектная система хранения данных, которую можно применять во многих сценариях приложений, включая, помимо прочего, следующие:

  • Крупномасштабное хранилище данных: поскольку MinIO использует распределенную среду, данные хранятся,Поэтому его можно легко масштабировать для удовлетворения потребностей организаций и предприятий, которым необходимо управлять большими объемами данных.
  • Хранилище изображений и медиа: потому чтоMinIOв необработанный двоичный файлданные Оптимизированный,поэтому очень подходитхранилищеизображение、Аудиои Видео и другие медиадокумент。это Также поддерживаетWebP、JPEGиPNGДругие форматы,Работает на нескольких устройствах и браузерах.
  • Облачные приложения: MinIO — это облачная система объектхранилище, работающая с Kubernetes, Docker. Инструменты оркестровки контейнеров, такие как SwarmиMesphere, легко интегрируются и хорошо удовлетворяют потребности облачных приложений.
  • Защита данных и аварийное восстановление: возможности записи нескольких копий MinIO и встроенная поддержка стирающего кодирования делают резервное копирование и восстановление данных простым и эффективным.
  • Распределенные вычисления и машинное обучение: MinIO обеспечивает STS (S3 Select) и интерфейс HDFS, поддерживает выполнение SQL-запросов непосредственно в хранилище данных, а также MapReduce и другие платформы параллельной обработки. Это делает его отличным выбором для больших Идеально подходит для задач распределенных вычислений, таких как данные, искусственный интеллект и машинное обучение.

Следует отметить, что перечисленные выше сценарии применения не являются всеми применимыми сценариями для MinIO. Это зависит от деталей и потребностей каждого варианта использования.

3. Основные шаги по реализации многочастной загрузки в Minio

Использование SpringBoot и MinIO для реализации многочастной загрузки, второй загрузки и возобновления загрузки в основном включает в себя следующие шаги:

  • Интерфейсная часть выбирает файлы и разрезает их. Технологии внешнего интерфейса, такие как JavaScript, можно использовать для разделения файлов на несколько фрагментов и генерации уникальных идентификаторов для каждого фрагмента.
  • Загрузите каждый осколок вMinIOобъектхранилище: Java вызывает MinIO SDK загружает каждый шард в MinIO, а имя KEY каждого шарда содержит базовое имя и идентификатор фрагмента.
  • Объединение всех фрагментов в конечный файл: после того, как фронтенд завершит загрузку всех фрагментов, в фоновом режиме разрабатывается интерфейс для объединения всех фрагментов в итоговый файл по уникальному идентификатору. Процесс объединения можно выполнить на сервере приложений или с помощью функции объединения самого объектного хранилища MinIO.
  • Обеспечьте мгновенную передачу: прежде чем внешний интерфейс загрузит фрагменты, он может определить, существует ли файл, на основе имени файла и значения MD5 файла, запрашивая фоновый интерфейс. Если он существует, URL-адрес файла может быть возвращен напрямую для достижения мгновенной передачи. передача.
  • Внедрить возобновление загрузки: при загрузке фрагментов на внешнем интерфейсе проблемы с сетью или сбои клиента приводят к прерыванию загрузки файла. В это время вам нужно только записать серийный номер загруженного фрагмента и флаг состояния и перезапустить загрузку со следующего фрагмента. .
  • Обработка ошибок и исключений. В процессе загрузки файлов вы можете столкнуться с различными проблемами, такими как сбои служб, перебои в работе сети, тайм-ауты обработки клиента и т. д. Поэтому необходимо добавить обработку ошибок и исключений, чтобы обеспечить бесперебойность всего процесса загрузки.

Вообще говоря, использовать SpringBoot и MinIO для реализации многочастной загрузки, второй загрузки и возобновления загрузки несложно. Его можно разработать и реализовать в соответствии с описанными выше шагами.

4. Установите Minio на Centos7.

Создать целевую папку

Язык кода:javascript
копировать
mkdir minio

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

Всем следует отметить, что сначала нам нужно установить docker. Соответствующие руководства по установке вы можете прочитать в моих предыдущих статьях и следовать инструкциям шаг за шагом. Я не буду здесь вдаваться в подробности! ! !

Язык кода:javascript
копировать
docker search minio

Используйте докер, чтобы извлечь изображение

Язык кода:javascript
копировать
docker pull minio/minio

Проверьте, успешно ли получено изображение

Язык кода:javascript
копировать
docker images

Запустите контейнер Minio

Язык кода:javascript
копировать
docker run -p 9000:9000 -p 9090:9090      --net=host      --name minio      -d --restart=always      -e "MINIO_ACCESS_KEY=IT@WangHui"      -e "MINIO_SECRET_KEY=IT@WangHui"            minio/minio server      /data --console-address ":9000" -address ":9090"

Обратите внимание, что существуют требования к надежности пароля, в противном случае будет сообщено об ошибке.

Это команда Docker для запуска контейнера MinIO. Конкретные параметры объясняются следующим образом:

  • -p: Сопоставьте внутренний порт контейнера с хостом. в 9000 и 9090 сопоставлено с хост-машиной соответственно 9000 и 9090 в порту.
  • --net=host: Добавьте контейнер в хост-сеть и поделитесь IP адрес.
  • --name minio: Укажите имя контейнера как minio。
  • --restart=always: настроить автоматический перезапуск контейнера после выхода.
  • -e: настраиватьсредапеременная。здесьнастраивать Получил двасредапеременная:MINIO_ACCESS_KEY и MINIO_SECRET_KEY,ценить соответственно IT@WangHui и IT@WangHui
  • --mount: Подключите каталог внутри контейнера к хосту. Здесь будет в контейнере /data Каталог монтируется на хост-компьютере /data в каталоге.
  • --console-address: Укажите консольный адрес контейнера. Здесь он установлен. :9000, что указывает на то, что его можно передать на хост. 9000 Порт доступа к консоли контейнера.
  • -address: Укажите сетевой адрес контейнера. Здесь он установлен. :9090, что означает, что вы можете пройти 9090 Служба контейнеров доступа к порту.

Совет: Доступ к странице 9000, код 9090. Совет: Доступ к странице 9000, код 9090. Совет: Доступ к странице 9000, код 9090.

Предупреждение об ошибке
причина:

Основная причина заключается в том, что при запуске контейнера докера или выполнении настройки докера также настраиваются параметры брандмауэра и перезапуск, что приводит к очистке конфигурации, связанной с докером, в результате чего цепочка докеров не отображается при запросе правил брандмауэра. iptables -L запрашивает цепочку iptables.

решать:

Это вызвано перезапуском firewalld, а перезапуск docker восстановит зарегистрированную цепочку iptables.

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

Язык кода:javascript
копировать
systemctl restart docker #Перезапускаем докер
docker ps -a #view runконтейнер
docker rm -f minio #Удалить контейнер по названию контейнера (обратите внимание на идентификацию своего)

Доступ в браузере после запускаhttp://localhost:9000вы можете получить доступminioграфический интерфейс,Как показано на рисунке:

Имя пользователя и пароль — это данные в параметрах запуска.

Если доступ не удался, это проблема брандмауэра или не добавлены последние два параметра параметров запуска. Других проблем не будет, если только контейнер не запустится успешно.

Чтобы просмотреть выпущенные порты, вы можете использовать следующую команду

Язык кода:javascript
копировать
 firewall-cmd --list-ports

Чтобы освободить порты 9000 и 9090 в CentOS 7, вы можете выполнить следующие действия:

1. Проверьте состояние брандмауэра.

Проверьте состояние брандмауэра с помощью следующей команды:

Язык кода:javascript
копировать
systemctl status firewalld

Если брандмауэр остановлен, запустите его:

Язык кода:javascript
копировать
systemctl start firewalld
2. Разрешить порту 9000 проходить через брандмауэр.

Разрешите TCP-трафик через порт 9000, используя следующую команду:

Язык кода:javascript
копировать
firewall-cmd --zone=public --add-port=9000/tcp --permanent
firewall-cmd --zone=public --add-port=9090/tcp --permanent

Это добавит в брандмауэр правило, разрешающее TCP-трафик через порт 9000. Чтобы сохранить это изменение навсегда, выполните следующую команду:

Язык кода:javascript
копировать
firewall-cmd --reload
3. Перезапустите сервисную оболочку брандмауэра.

Перезапустите службу брандмауэра, используя следующую команду:

Язык кода:javascript
копировать
systemctl restart firewalld

Теперь вы успешно освободили порты 9000 и 9090 в CentOS 7.

5. Настройте среду Springboot.

Структура кода

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

Язык кода:javascript
копировать
<!-- действоватьminioизjavaклиент-->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.2</version>
</dependency>
<!-- действоватьminioизjavaклиент-->
 <dependency>
    <groupId>io.minio</groupId>
     <artifactId>minio</artifactId>
     <version>8.2.1</version>
</dependency>
<!--        jwtАутентификация зависит от-->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.2</version>
</dependency>

Создание контейнера-контейнера

Получить учетные данные для доступа к API

Записать файл конфигурации

Язык кода:javascript
копировать
server:
    port: 8080
spring:
    servlet:
        multipart:
            max-file-size: 10MB
            max-request-size: 10MB
    #minioКонфигурация
    minio:
        access-key: dAMaxkWaXUD1CV1JHbqw
        secret-key: AXt3SD0JFkDENFbMeJKOOQb5wj8KvabZWu33Rs84
        url: http://192.168.18.14:9090  #Адрес доступа
        bucket-name: wanghui

Первый — это конфигурация сервера:

  • Номер порта — 8080, который используется для прослушивания запросов.
  • использовалServletсправитьсяmultipart/form-dataдобрыйформаизпросить。
  • при полученииmultipart/form-dataдобрыйформаизпросить时,встреча Волязагрузитьиздокумент Размер ограничен10MBв пределах,И ограничьте размер запроса до 10 МБ.

Далее идет настройка minio:

  • access-keyиsecret-keyэто визитminioСлужитьизсертификат,Его необходимо заполнить в соответствии с реальной ситуацией.
  • URL-адрес — это адрес службы minio, и его необходимо заполнить в соответствии с реальной ситуацией.
  • bucket-nameдахранилищедокументизведроимя,Его необходимо заполнить в соответствии с реальной ситуацией.

статус HTTP-запроса

Язык кода:javascript
копировать
package com.xiaohui.utils;

/**
 * @Description статус HTTP-запроса
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/01
 */
public class HttpStatus
{
    /**
     * Операция прошла успешно
     */
    public static final int SUCCESS = 200;

    /**
     * объект успешно создан
     */
    public static final int CREATED = 201;

    /**
     * Запрос принят
     */
    public static final int ACCEPTED = 202;

    /**
     * Операция выполнена успешно, но данные не возвращены.
     */
    public static final int NO_CONTENT = 204;

    /**
     * Ресурс удален
     */
    public static final int MOVED_PERM = 301;

    /**
     * Перенаправление
     */
    public static final int SEE_OTHER = 303;

    /**
     * Ресурс не был изменен
     */
    public static final int NOT_MODIFIED = 304;

    /**
     * Неверный список параметров (отсутствует, несоответствие формата)
     */
    public static final int BAD_REQUEST = 400;

    /**
     * Несанкционированный
     */
    public static final int UNAUTHORIZED = 401;

    /**
     * Доступ ограничен, срок авторизации истек
     */
    public static final int FORBIDDEN = 403;

    /**
     * Ресурс, сервис не найден
     */
    public static final int NOT_FOUND = 404;

    /**
     * Запрещенный http-метод
     */
    public static final int BAD_METHOD = 405;

    /**
     * Конфликт ресурсов или ресурс заблокирован
     */
    public static final int CONFLICT = 409;

    /**
     * Неподдерживаемые данные, тип носителя
     */
    public static final int UNSUPPORTED_TYPE = 415;

    /**
     * Внутренняя ошибка системы
     */
    public static final int ERROR = 500;

    /**
     * интерфейс не реализован
     */
    public static final int NOT_IMPLEMENTED = 501;

    /**
     * Системное предупреждающее сообщение
     */
    public static final int WARN = 601;
}

Общая постоянная информация

Язык кода:javascript
копировать
package com.xiaohui.utils;

import io.jsonwebtoken.Claims;

/**
 * @Description Общая постоянная информация
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/01
 */
public class Constants
{
    /**
     * UTF-8 набор символов
     */
    public static final String UTF8 = "UTF-8";

    /**
     * GBK набор символов
     */
    public static final String GBK = "GBK";

    /**
     * www основной домен
     */
    public static final String WWW = "www.";

    /**
     * HTTP-запрос
     */
    public static final String HTTP = "http://";

    /**
     * https-запрос
     */
    public static final String HTTPS = "https://";

    /**
     * универсальный знак успеха
     */
    public static final String SUCCESS = "0";

    /**
     * Общий флаг отказа
     */
    public static final String FAIL = "1";

    /**
     * Вход успешен
     */
    public static final String LOGIN_SUCCESS = "Success";

    /**
     * Выйти
     */
    public static final String LOGOUT = "Logout";

    /**
     * зарегистрироваться
     */
    public static final String REGISTER = "Register";

    /**
     * Ошибка входа
     */
    public static final String LOGIN_FAIL = "Error";
 
    /**
     * Срок действия проверочного кода (минуты)
     */
    public static final Integer CAPTCHA_EXPIRATION = 2;

    /**
     * жетон
     */
    public static final String TOKEN = "token";

    /**
     * жетонпрефикс
     */
    public static final String TOKEN_PREFIX = "Bearer ";

    /**
     * жетонпрефикс
     */
    public static final String LOGIN_USER_KEY = "login_user_key";

    /**
     * ID пользователя
     */
    public static final String JWT_USERID = "userid";

    /**
     * Имя пользователя
     */
    public static final String JWT_USERNAME = Claims.SUBJECT;

    /**
     * Аватар пользователя
     */
    public static final String JWT_AVATAR = "avatar";

    /**
     * время создания
     */
    public static final String JWT_CREATED = "created";

    /**
     * Разрешения пользователя
     */
    public static final String JWT_AUTHORITIES = "authorities";

    /**
     * Путь сопоставления ресурсов префикс
     */
    public static final String RESOURCE_PREFIX = "/profile";

    /**
     * RMI удаленный вызов метода
     */
    public static final String LOOKUP_RMI = "rmi:";

    /**
     * LDAP удаленный вызов метода
     */
    public static final String LOOKUP_LDAP = "ldap:";

    /**
     * LDAPS удаленный вызов метода
     */
    public static final String LOOKUP_LDAPS = "ldaps:";

    /**
     * Белый список запланированных задач Конфигурация (только те имена пакетов, к которым разрешен доступ, вы можете добавить их самостоятельно, если вам нужно что-то еще)
     */
    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };

    /**
     * Персонажи, нарушающие запланированные задания
     */
    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
            "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
}

Создать класс конфигурации Minio

Язык кода:javascript
копировать
package com.xiaohui.config;

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description minioКонфигурация
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/02
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
public class MinioConfig {
    private String accessKey;

    private String secretKey;

    private String url;

    private String bucketName;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .endpoint(url)
                .credentials(accessKey,secretKey)
                .build();
    }
}

Этот код представляет собой класс конфигурации в Java, используемый для настройки свойств, связанных с MinIO (службой хранения объектов). Конкретно:

  • @ConfigurationВ аннотации указано, что этодаодин Конфигурациядобрый,Используется для внедрения свойств, определенных в этом классе, в другие компоненты.
  • @ConfigurationPropertiesВ аннотации указано, чтодобрыйиспользовалspring.minio.*префиксизатрибуты приходят КонфигурацияMinioСвязанныйизсвойство。
  • @DataАннотации генерируются автоматическиgetterиsetterметод,Упрощенное написание кода.
  • accessKeyиsecretKeyАтрибуты соответственно представляют собой ключи доступа.иключценить,Используется для подключения к сервису MinIO.
  • Атрибут url представляет URL-адрес службы MinIO.
  • bucketNameПредставление атрибутахранилище Название сегмента。
  • @BeanВ аннотации указано, чтоminioClient()методвозвращатьсяизобъектзарегистрироватьсядляbean,для использования в других компонентах.
  • minioClient()методвернулMinioClientобъект,Используется для подключения к сервисам MinIO и работы с сегментами хранилища. в,endpoint()методиспользуется длянастраиватьMinIOСлужитьизURLадрес,credentials()методиспользуется длянастраиватьдоступключиключценить。

Создать класс инструментов Minio

Язык кода:javascript
копировать
package com.xiaohui.utils;


import com.xiaohui.config.MinioConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description Минио инструменты
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/02
 */

@Component
public class MinioUtils {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig configuration;

    /**
     * @param name имя
     * @return boolean
     * @Description description: Определить, существует ли ведро, создать его, если оно не существует.
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public boolean existBucket(String name) {
        boolean exists;
        try {
            exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
                exists = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            exists = false;
        }
        return exists;
    }

    /**
     * @param bucketName хранилищеbucketимя     * @return {@link Boolean }
     * @Description создаватьхранилищеbucket     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * @param bucketName хранилищеbucketимя     * @return {@link Boolean }
     * @Description удалитьхранилищеbucket     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * @param fileName Имя файла
     * @param time     время
     * @return {@link Map }
     * @Description Получить временную подпись для загрузки
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    @SneakyThrows
    public Map getPolicy(String fileName, ZonedDateTime time) {
        PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);
        postPolicy.addEqualsCondition("key", fileName);
        try {
            Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
            HashMap<String, String> map1 = new HashMap<>();
            map.forEach((k, v) -> {
                map1.put(k.replaceAll("-", ""), v);
            });
            map1.put("host", configuration.getUrl() + "/" + configuration.getBucketName());
            return map1;
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (XmlParserException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param objectName объектимя     * @param method     метод
     * @param time       время
     * @param timeUnit   времяединица
     * @return {@link String }
     * @Description Получить URL загруженного файла
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(method)
                    .bucket(configuration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (XmlParserException e) {
            e.printStackTrace();
        } catch (ServerException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * @param file     документ
     * @param fileName Имя файла
     * @Description загрузитьдокумент
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public void upload(MultipartFile file, String fileName) {
        // Используйте putObject для загрузки документа в корзину хранилища.
        try {
            InputStream inputStream = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(configuration.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (XmlParserException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param objectName объектимя     * @param time       время
     * @param timeUnit   времяединица
     * @return {@link String }
     * @Description в соответствии сfilenameполучатьдокументдоступадрес
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public String getUrl(String objectName, int time, TimeUnit timeUnit) {
        String url = null;
        try {
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(configuration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (XmlParserException e) {
            e.printStackTrace();
        } catch (ServerException e) {
            e.printStackTrace();
        }
        return url;
    }

    /**
     * @param fileName
     * @return {@link ResponseEntity }<{@link byte[] }>
     * @Description description: скачатьдокумент
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public ResponseEntity<byte[]> download(String fileName) {
        ResponseEntity<byte[]> responseEntity = null;
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());
            out = new ByteArrayOutputStream();
            IOUtils.copy(in, out);
            //Инкапсулируем возвращаемое значение
            byte[] bytes = out.toByteArray();
            HttpHeaders headers = new HttpHeaders();
            try {
                headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            headers.setContentLength(bytes.length);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setAccessControlExposeHeaders(Arrays.asList("*"));
            responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseEntity;
    }

    /**
     * @param objectFile объектдокумент
     * @return {@link String }
     * @Description в соответствии сдокументимяиведрополучатьдокументпуть
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    public String getFileUrl(String objectFile) {
        try {

            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(configuration.getBucketName())
                    .object(objectFile)
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


}

Этот код представляет собой класс инструментов для загрузки и скачивания файлов с использованием службы объектного хранилища Alibaba Cloud (OSS). Конкретные функции заключаются в следующем:

  • getPolicy(String fileName, ZonedDateTime time):в соответствии сдокументимяивремяштамп Получить временную подпись для загрузки。
  • getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit):Получить URL загруженного файла。
  • upload(MultipartFile file, String fileName):Волядокументзагрузить вOSSсередина。
  • getUrl(String objectName, int time, TimeUnit timeUnit):получатьдокументизскачатьurl。

Типы перечислений используются в коде для определения различных методов загрузки и скачивания.

Аннотации используются@Autowiredот автоматического впрыскаMinioClientобъект。

Этот класс инструментов не предоставляет механизма обработки исключений и его необходимо дополнять в соответствии с реальной ситуацией.

Создать класс инструмента запроса Ajax

Язык кода:javascript
копировать

/**
 * @Description результаты ajax
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/01
 */
public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;

    /** код состояния */
    public static final String CODE_TAG = "code";

    /** Возврат контента */
    public static final String MSG_TAG = "msg";

    /** данныеобъект */
    public static final String DATA_TAG = "data";

    /**
     * Инициализировать вновь созданный AjaxResult объект, что делает его пустым сообщением.
     */
    public AjaxResult()
    {
    }

    /**
     * Инициализировать вновь созданный AjaxResult объект
     *
     * @param code код состояния
     * @param msg Возврат контента
     */
    public AjaxResult(int code, String msg)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }

    /**
     * Инициализировать вновь созданный AjaxResult объект
     *
     * @param code код состояния
     * @param msg Возврат контента
     * @param data данныеобъект
     */
    public AjaxResult(int code, String msg, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (data!=null)
        {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * Вернуть сообщение об успехе
     *
     * @return сообщение об успехе
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("Операция прошла успешно");
    }

    /**
     * Возвращение успешных
     *
     * @return сообщение об успехе
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("Операция прошла успешно", data);
    }

    /**
     * Вернуть сообщение об успехе
     *
     * @param msg Возврат контента
     * @return сообщение об успехе
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }

    /**
     * Вернуть сообщение об успехе
     *
     * @param msg Возврат контента
     * @param data данныеобъект
     * @return сообщение об успехе
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
    }

    /**
     * Возврат предупреждающего сообщения
     *
     * @param msg Возврат контента
     * @return предупреждающее сообщение
     */
    public static AjaxResult warn(String msg)
    {
        return AjaxResult.warn(msg, null);
    }

    /**
     * Возврат предупреждающего сообщения
     *
     * @param msg Возврат контента
     * @param data данныеобъект
     * @return предупреждающее сообщение
     */
    public static AjaxResult warn(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.WARN, msg, data);
    }

    /**
     * Возврат сообщения об ошибке
     *
     * @return сообщение об ошибке
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("Операция не удалась");
    }

    /**
     * Возврат сообщения об ошибке
     *
     * @param msg Возврат контента
     * @return сообщение об ошибке
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }

    /**
     * Возврат сообщения об ошибке
     *
     * @param msg Возврат контента
     * @param data данныеобъект
     * @return сообщение об ошибке
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.ERROR, msg, data);
    }

    /**
     * Возврат сообщения об ошибке
     *
     * @param code код состояния
     * @param msg Возврат контента
     * @return сообщение об ошибке
     */
    public static AjaxResult error(int code, String msg)
    {
        return new AjaxResult(code, msg, null);
    }

    /**
     * Удобный цепной вызов
     *
     * @param key ключ
     * @param value ценить
     * @return данныеобъект
     */
    @Override
    public AjaxResult put(String key, Object value)
    {
        super.put(key, value);
        return this;
    }
}

Создать слой интерфейса операций с файлами Minio

Язык кода:javascript
копировать
package com.xiaohui.controller;

import com.xiaohui.utils.AjaxResult;
import com.xiaohui.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;

/**
 * @Description контроллер загрузки мини-документов
 * @Author IT-одноклассник Сяохуэй
 * @Date 2023/06/02
 */
@CrossOrigin
@RestController
@RequestMapping("/api")
public class MinioFileUploadController {
    @Autowired
    private MinioUtils minioUtils;

    /**
     * @param file     документ
     * @param fileName Имя файла
     * @return {@link AjaxResult }
     * @Description загрузитьдокумент
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    @GetMapping("/upload")
    public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, String fileName) {

        minioUtils.upload(file, fileName);
        return AjaxResult.success("Загрузка прошла успешно");

    }

    /**
     * @param fileName Имя файла
     * @return {@link ResponseEntity }
     * @Description dowloadдокумент
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    @GetMapping("/dowload")
    public ResponseEntity dowloadFile(@RequestParam("fileName") String fileName) {
        return minioUtils.download(fileName);
    }

    /**
     * @param fileName Имя файла
     * @return {@link AjaxResult }
     * @Description получатьдокументurl
     * @Author IT-одноклассник Сяохуэй
     * @Date 2023/06/02
     */
    @GetMapping("/getUrl")
    public AjaxResult getFileUrl(@RequestParam("fileName") String fileName){
        HashMap map=new HashMap();
        map.put("FileUrl",minioUtils.getFileUrl(fileName));
        return AjaxResult.success(map);
    }
}

6. Функциональное тестирование

Загрузка большого файла Minio

Адрес большого файла Minio

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose