【问题标题】:Java Spring - Can't save image to static folderJava Spring - 无法将图像保存到静态文件夹
【发布时间】:2021-06-14 13:54:17
【问题描述】:

我想将图像保存到resources/static/photos 文件,但 Java/Kotlin 找不到它。不过它很好地找到了project/photos

这是一段代码,在 Kotlin 中,但我认为这并不重要

    override fun saveImage(imageFile: MultipartFile, id: String) {
        val bytes = imageFile.bytes

        val path = Paths.get(
            "$imagesFolderPath$id.${imageFile.originalFilename.substringAfter('.')}")
        Files.write(path, bytes)
    }

我需要将其保存到 resources/static/photos 以便能够从 thymeleaf 访问它。

谢谢。

【问题讨论】:

  • 在运行时,resources 文件夹是只读的。您不能在那里保存文件,它们必须保存在源文件的外部。
  • 即使你让它工作,它也只会在你开发时工作。一旦你将你的应用程序打包为一个档案(jar / war / 不管),你就不能像这样将新文件添加到你的类路径中。您应该寻找替代模板解析器。
  • 问题是thymeleaf 除了那些资源之外什么都看不到,java 看不到那些资源。我该如何解决这个问题?
  • 通过添加另一个模板解析器。默认情况下,thymeleaf 附加了一个模板解析器,它只查看resources。但是您可以添加尽可能多的替代模板解析器,它可以在您想要的任何地方查找模板。编辑:你很可能想要这样的东西:stackoverflow.com/questions/25156153/…
  • 您不需要额外的模板解析器来加载图像。将图像保存在文件系统的某个位置(不在 jar/war 中),然后有一个控制器再次为它们提供服务。

标签: java spring kotlin thymeleaf


【解决方案1】:

问题是,您可以在开发阶段将文件保存在项目目录中,但是一旦您将项目导出为应用程序包(.jar-application,@ 987654322@-archive 等),因为在那时,以前是文件系统上实际目录的所有内容现在都是单个文件。

这是一个示例,您可以如何通过将图像保存在可配置文件夹中来实现这一点:

我从来没有用 Kotlin 写过一行代码。我希望这个例子对你有帮助,即使它是用 Java 编写的。

这是一个示例控制器,它接受要在 POST 端点上上传和在 GET 端点上下载的图像:

package example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.PathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Optional;

@RestController
public class MyController {

    private final Path imageStorageDir;

    /*
    The target path can be configured in the application.properties / application.yml or using the parameter -Dimage-storage.dir=/some/path/
     */
    @Autowired
    public MyController(@Value("${image-storage-dir}") Path imageStorageDir) {
        this.imageStorageDir = imageStorageDir;
    }

    @PostConstruct
    public void ensureDirectoryExists() throws IOException {
        if (!Files.exists(this.imageStorageDir)) {
            Files.createDirectories(this.imageStorageDir);
        }
    }

    /*
    This enables you to perform POST requests against the "/image/YourID" path
    It returns the name this image can be referenced on later
     */
    @PostMapping(value = "/image/{id}", produces = MediaType.TEXT_PLAIN_VALUE)
    public String uploadImage(@RequestBody MultipartFile imageFile, @PathVariable("id") String id) throws IOException {
        final String fileExtension = Optional.ofNullable(imageFile.getOriginalFilename())
                .flatMap(MyController::getFileExtension)
                .orElse("");

        final String targetFileName = id + "." + fileExtension;
        final Path targetPath = this.imageStorageDir.resolve(targetFileName);

        try (InputStream in = imageFile.getInputStream()) {
            try (OutputStream out = Files.newOutputStream(targetPath, StandardOpenOption.CREATE)) {
                in.transferTo(out);
            }
        }

        return targetFileName;
    }

    /*
    This enables you to download previously uploaded images
     */
    @GetMapping("/image/{fileName}")
    public ResponseEntity<Resource> downloadImage(@PathVariable("fileName") String fileName) {
        final Path targetPath = this.imageStorageDir.resolve(fileName);
        if (!Files.exists(targetPath)) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(new PathResource(targetPath));
    }

    private static Optional<String> getFileExtension(String fileName) {
        final int indexOfLastDot = fileName.lastIndexOf('.');

        if (indexOfLastDot == -1) {
            return Optional.empty();
        } else {
            return Optional.of(fileName.substring(indexOfLastDot + 1));
        }
    }
}

假设您上传的图片的文件结尾为.png,ID 为HelloWorld,然后您可以使用以下网址访问图片: http://localhost:8080/image/HelloWorld.png

使用此 URL,您还可以在任何 thymeleaf 模板中引用图像:

&lt;img th:src="@{/image/HelloWorld.png}"&gt;&lt;/img&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-01
    • 2021-04-05
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2015-02-09
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多