Лучшая практика для Java SpringBoot — загружать файлы локально в каталог ресурсов и постоянно сохранять загрузку.
Лучшая практика для Java SpringBoot — загружать файлы локально в каталог ресурсов и постоянно сохранять загрузку.

Общие требования: загрузка файлов для серверных проектов Java является очень распространенным требованием. Как правило, в официальных проектах мы используем стороннюю операционную систему Alibaba Cloud для загрузки файлов. Однако, если это просто в учебных целях, мы можем загружать их напрямую. в локальную папку на вашем компьютере.

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

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

Идеи реализации

Мы можем получить путь к загруженному файлу с помощью метода ResourceUtils.getURL("classpath:").getPath(). Мы получаем абсолютный путь к скомпилированному каталогу target/classes. Файлы, загруженные внешним интерфейсом, могут быть. напрямую сохраняется здесь. Например, следующий каталог: target/classes/upload/logo.jpg, адрес загрузки, возвращаемый во внешний интерфейс, выглядит следующим образом: http://localhost:8080/upload/logo.jpg.

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

Что делать? Если вы внимательно подумаете, разве в нашем проекте нет каталога с именем resources, который используется для хранения статических ресурсов? Этот каталог обычно передается в хранилище кода для управления. Тогда нельзя ли отправлять файлы, которые мы загружаем каждый раз? на склад вместе? Постоянное хранение достигается.

Просто сделайте это и сохраните файл непосредственно в каталоге resources/upload. Как только серверная часть запустится и внешний интерфейс загрузит файл, файл действительно будет сохранен в каталоге resources/upload. Присмотревшись, я увидел, что это неправильно. Адрес внешнего интерфейса не имел доступа к только что загруженному файлу, поскольку в каталоге target/classes не было нового загруженного файла. После компиляции файлы в папке. Каталог ресурсов был синхронизирован с каталогом target/classes. Доступ действительно возможен, но мы не можем повторно щелкнуть мышью для компиляции и повторного запуска каждый раз, когда мы его загружаем.

Подводя итог, я объединю ресурсы и цель и сохраню файлы в этих двух каталогах одновременно. Можно ли будет добиться постоянного хранения и доступа в реальном времени?

окончательное решение

Используйте System.getProperty("user.dir"), чтобы получить рабочий каталог проекта, а затем добавьте каталог структуры проекта, чтобы получить абсолютный путь к каталогу ресурсов; для рабочего каталога цели/классов используйте ResourceUtils.getURL( "classpath:").getPath() получает.

Обратите внимание: если последний загруженный каталог ресурсов обращается к 404, проверьте путь статического ресурса Spring.mvn в application.yml, правила фильтрации ресурсов в pom.xml и было ли перехвачено статическое сопоставление ресурсов addResourceHandler, настроенное в WebMvcConfiguration.

Наконец, интерфейсная часть передала файл File, но на самом деле нет возможности циклически сохранить файл в несколько каталогов. После успешного сохранения первой папки последующие сообщат об ошибке. файл на компьютере. Его можно сохранить только в одном каталоге. Если вы хотите сохранить его в другой каталог, просто скопируйте его самостоятельно. Мы сохраняем первый каталог напрямую, и вы можете напрямую скопировать второй. каталог, используя FileCopyUtils.copy, предоставленный Spring.

Полный код

UploadFileUtil.java

Язык кода:javascript
копировать
packagecom.sky.utils;

importjava.io.File;
importjava.io.FileNotFoundException;
importjava.io.IOException;
importjava.util.ArrayList;
importjava.util.List;
importjava.util.UUID;

importorg.springframework.util.FileCopyUtils;
importorg.springframework.util.ResourceUtils;
importorg.springframework.web.multipart.MultipartFile;

publicclassUploadFileUtil{
    /**
     * Получить путь сохранения документа
     *
     * @return File
     * @throws FileNotFoundException
     */
    staticList<File>getUploadDirectory()throwsFileNotFoundException{
        // Приобретение среды разработки target/classes Каталог: После очистки и повторной установки он исчезнет.
        File targetPath =newFile(ResourceUtils.getURL("classpath:").getPath());
        // System.out.printf("Абсолютный путь запуска проекта:" + path.getAbsolutePath());
        // выход xx/sky-parent/sky-server/target/classes
        // производственная среда 不存существовать target/classes Оглавление
        if(!targetPath.exists()){
            // Будьте в курсе событий
            targetPath =newFile("");
        }

        // среда разработки resources Оглавление: Можно сохранить навсегда.
        String resourcesPath =System.getProperty("user.dir")+"/sky-server/src/main/resources";
        // System.out.printf("resources Оглавление path:" + resourcesPath);
        File path =newFile(resourcesPath);


        File upload =newFile(path.getAbsolutePath(),"upload");
        File uploadTarget =newFile(targetPath.getAbsolutePath(),"upload");

        // Создать, если существования не существует
        if(!upload.exists()){
            upload.mkdirs();
        }
        if(!uploadTarget.exists()){
            uploadTarget.mkdirs();
        }

        List<File> files =newArrayList<File>();
        files.add(upload);
        files.add(uploadTarget);

        // System.out.printf("текущий Оглавление:" + files);

        return files;
    }

    publicstaticStringupload(MultipartFile myFile,String dir)throwsIOException{
        String filePath ="";
        if(!myFile.isEmpty()){
            try{
                String filename = myFile.getOriginalFilename();
                filename = UUID.randomUUID()+ filename.substring(filename.lastIndexOf("."));

                // Причина, по которой он сохраняется в resources и target два Оглавление,С учетом разработки и тестированияи永久保存
                // Сохранить только вresourcesОглавление Приходится каждый раз перезагружатькомпилировать Вниз,Мишень исчезнет после очистки и упаковки.
                List<File> files =getUploadDirectory();

                // Обратите внимание, что этот внутридокумент не может быть записан в цикле для нескольких Оглавлений одновременно.,Сохранил первый,Второй надо копировать
                Файл curFile =newFile(files.get(0), имя файла);
                мой Файл.transferTo(curFile);
                FileCopyUtils.copy(curFile,newFile(files.get(1), имя файла));
                //для (Файл f: файлы) {
                    //Файл curFile = новый файл(f, имя файла);
                    //myFile.transferTo(curFile);
                //}

                filePath = "http://localhost:8080/upload/"+ имя файла;
            }catch(Исключение е){
                е.printStackTrace();
            }
        }

        вернуть путь к файлу;
    }
}

application.yml

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

spring:
  mvc:
    static-path-pattern: /upload/**

WebMvcConfiguration

Язык кода:javascript
копировать
packagecom.sky.config;

importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;


importjava.util.List;

/**
 * Класс конфигурации, регистрация компонентов, связанных с веб-слоем.
 */
@Configuration
publicclassWebMvcConfigurationextendsWebMvcConfigurationSupport{
    /**
     * Установить статическое сопоставление ресурсов
     * @param registry
     */
    protectedvoidaddResourceHandlers(ResourceHandlerRegistry registry){
        // Установите статическое сопоставление ресурсов загруженного документа, приложение внутрииз mvc внутри也要设置Вниз静态Оглавление
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("classpath:/upload/","file:upload/");
    }
}

Пример использования

Получите файл файла, загруженный внешним интерфейсом, используя форму в контроллере.

Язык кода:javascript
копировать
packagecom.sky.controller.common;

importcom.sky.result.Result;
importcom.sky.utils.UploadFileUtil;
importio.swagger.annotations.Api;
importio.swagger.annotations.ApiOperation;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.PostMapping;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.RestController;
importorg.springframework.web.multipart.MultipartFile;

importjava.io.IOException;

/**
 * общественный запрос
 */
@RestController
@RequestMapping("/common")
@Api(tags ="публичный")
@Slf4j
publicclassCommonController{

    @PostMapping("/upload")
    @ApiOperation("загрузитьдокумент")    publicResultuploadFile(MultipartFile file)throwsIOException{
        log.info("загрузитьдокумент:{}", file);
        String fileUrl =UploadFileUtil.upload(file,"");
        if(fileUrl ==null|| fileUrl ==""){
            returnResult.error("Не удалось загрузить");
        }
        returnResult.success(fileUrl);
    }
}
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