Java SpringBoot implements local uploading of files to the resources directory for permanent storage and downloading

Requirement background: Uploading files for Java backend projects is a very common requirement. Generally, in formal projects, we use third-party Alibaba Cloud OSS to upload files. However, if it is just for learning purposes, then we may upload them directly. to a local folder on your computer.

But if you upload it to a folder on your computer, you won’t be able to see it on another computer. After uploading general files, we need to return the download path to the front-end file. If it is a random folder on the computer, then the front-end It’s probably inaccessible.

In order to solve the problem of front-end access, we can upload the file to the static resource directory of the back-end service, so that the front-end can directly access it through the address and port of the back-end service plus the resource path.

Implementation ideas

We can use the ResourceUtils.getURL(“classpath:”).getPath() method to obtain the path of the uploaded file. What we get is the absolute path of the compiled target/classes directory, and the files uploaded by the front end can be stored directly. Go to the directory below, for example: target/classes/upload/logo.jpg. The download address returned to the front end is like this: http://localhost:8080/upload/logo.jpg. [1]

The above idea does solve the problem of uploading and downloading, but the target directory will change and will not be submitted to the code warehouse. If we clean up and then recompile or change the computer to compile, the previously uploaded files will be gone.

what should I do? If you think about it carefully, doesn’t our project have a directory called resources that is used to store static resources? This directory is normally submitted to the code warehouse for management. Then every file we upload can be submitted to the warehouse together. This part Permanent storage is achieved.

Just do it and save the file directly to the resources/upload directory. As soon as the backend runs and the frontend uploads, the file is indeed saved to the resources/upload directory. After a closer look, I saw that it was wrong. The front-end address did not access the newly uploaded file, because there was no newly uploaded file in the target/classes directory. Click compile again. After compilation, the files in the resources directory were synchronized to the target/classes directory. It was indeed Access can be achieved, but we can’t re-click to compile and re-run every time we upload it.

As a final summary, I will combine resources and target and save the files in these two directories at the same time. Will it be possible to achieve permanent storage and real-time access?

Ultimate solution

Use System.getProperty(“user.dir”) to get the working directory of the project, and then add the project structure directory to get the absolute path of the resources directory; for the target/classes running directory, use ResourceUtils.getURL(\ “classpath:”).getPath() gets.

Note that if the last uploaded resource directory accesses 404, check the static resource path of spring.mvn in application.yml, the resources filtering rules in pom.xml, and whether the addResourceHandler static resource mapping configured in WebMvcConfiguration has been intercepted.

Finally, the front-end passed a File file, but there is actually no way to save a file to multiple directories in a loop. After the first folder is saved successfully, the subsequent ones will report an error. Think about how we usually save a file on the computer. It can only be saved to one directory. If you want to save it to another directory, just copy it yourself. The same is true here. We save the first directory directly, and you can directly copy the second directory using FileCopyUtils.copy provided by spring. File will do.

Complete code

UploadFileUtil.java

package com.sky.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.springframework.util.FileCopyUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

public class UploadFileUtil {
    
     * Get the file saving path
     *
     * @return File
     * @throws FileNotFoundException
     */
    static List<File> getUploadDirectory() throws FileNotFoundException {
        
        File targetPath = new File(ResourceUtils.getURL("classpath:").getPath());
        
        
        
        if (!targetPath.exists()) {
            
            targetPath = new File("");
        }

        
        String resourcesPath = System.getProperty("user.dir") + "/sky-server/src/main/resources";
        
        File path = new File(resourcesPath);


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

        
        if (!upload.exists()) {
            upload.mkdirs();
        }
        if (!uploadTarget.exists()) {
            uploadTarget.mkdirs();
        }

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

        

        return files;
    }

    public static String upload(MultipartFile myFile, String dir) throws IOException {
        String filePath = "";
        if (!myFile.isEmpty()) {
            try {
                String filename = myFile.getOriginalFilename();
                filename = UUID.randomUUID() + filename.substring(filename.lastIndexOf("."));

                
                
                List<File> files = getUploadDirectory();

                
                File curFile = new File(files.get(0), filename);
                myFile.transferTo(curFile);
                FileCopyUtils.copy(curFile, new File(files.get(1), filename));
                
                    
                    
                

                filePath = "http://localhost:8080/upload/" + filename;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return filePath;
    }
}

application.yml

server:
  port: 8080

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

WebMvcConfiguration

package com.sky.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;


import java.util.List;


 * Configuration class, register web layer related components
 */
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    
     * Set static resource mapping
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("classpath:/upload/", "file:upload/");
    }
}

Usage examples

Receive the File file uploaded by the front end using the form in the controller

package com.sky.controller.common;

import com.sky.result.Result;
import com.sky.utils.UploadFileUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;


 *Public request
 */
@RestController
@RequestMapping("/common")
@Api(tags = "public")
@Slf4j
public class CommonController {

    @PostMapping("/upload")
    @ApiOperation("Upload file")
    public Result uploadFile(MultipartFile file) throws IOException {
        log.info("Upload file: {}", file);
        String fileUrl = UploadFileUtil.upload(file, "");
        if (fileUrl == null || fileUrl == "") {
            return Result.error("Upload failed");
        }
        return Result.success(fileUrl);
    }
}

Reference materials

[1]

http://localhost:8080/upload/logo.jpg. : https://link.juejin.cn/?target=http://localhost:8080/upload/logo.jpg%E3%80%82

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 138132 people are learning the system