我是Spring-Boot的新手...... 我想上传图片或视频,并将它们存储在一个持久的文件夹中" upload-storage"在我的服务器项目的类路径中。我不想将它们存储在数据库中(20 Mo) Spring-Boot将它们存储在目标/上传存储中 功能:我可以通过控制器和Thymeleaf在视图上显示视频。我可以关闭tomcat,关闭浏览器,再次打开它们:功能 但是第二天,上传存储就消失了! 我认为我不会使用这个好的过程 但我发现如何上传图片:好的。我找到了如何在class-path中显示文件夹中的图像:ok。我找到了如何将图像上传到数据库。但没有什么可以将上传的图像存储在一个持久文件夹中 你能帮助我吗 ?你能告诉我好的过程吗?
一些细节:
我有一个实体"视频"存储视频的名称,扩展名,长度......
我有" VideoRepository"和" VideoService"使用"视频"来管理请求
我有一个" StorageService"和" StorageServiceImpl"管理视频和图像的上传:它上传视频并将其保存在名为" upload-storage"的文件夹中。 :我会再往前走吧
我有一个videoForm.html首先用一个表单来选择一个文件并将其发送到" UploadController",然后另一个表单来显示视频,从视频中提取的数据,修改名称或添加精度,并将此表单发送给" VideoController"谁拯救了实体。
" UploadController"的一部分代码:
`
@Controller
public class UploadController扩展了BaseController {
private final StorageService storageServiceImpl;
@Autowired
public UploadController(StorageService storageServiceImpl) {
this.storageServiceImpl = storageServiceImpl;
}
@PostMapping("/upload")
public String recupereUpload(@RequestParam("file") MultipartFile file,Model model){
String filename ="";
try {
final long limit = 200 * 1024 * 1024;
if (file.getSize() > limit) {
model.addAttribute("message", "Taille du fichier trop grand (>200MB)");
model.addAttribute("ok", false );
}
filename = storageServiceImpl.store(file);
model.addAttribute("filename", filename);
model.addAttribute("message", "Le téléchargement de " + filename+" est réussi !");
} catch (Exception e) {
model.addAttribute("message", "FAIL to upload " + filename + "!");
model.addAttribute("ok", false );
}
Video video = new Video();
model.addAttribute("ok", true );
model.addAttribute("video", video);
String baseName = storageServiceImpl.getBaseName(filename);
String ext = storageServiceImpl.getExtension(filename);
model.addAttribute("nom", baseName);
model.addAttribute("ext", ext);
model.addAttribute("nomorigin", filename);
model.addAttribute("size", Math.round(file.getSize()/1024));
String typExt = storageServiceImpl.getType(ext);
model.addAttribute("typExt", typExt);
return "elementVideo/videoForm";
}
`
" StorageServiceImpl"有不同的方法:
getExtension(String filename){...}
getType(String ext){...}
getType(String ext){...}
getBaseName(String filename){...}
主要方法是存储(MultipartFile文件){...}:
@Service
public class StorageServiceImpl implements StorageService {
private final Path storageLocation = Paths.get("upload-storage");
@Override
public String store(MultipartFile file) {
try {
// Vérification de l'existence :
if (file.isEmpty()) {
throw new Exception("Failed to store empty file " + file.getOriginalFilename() );
}
// Vérification de la nature et traitement du fichier uploadé :
String ext = getExtension(file.getOriginalFilename());
String[] extAutorise = {"mp4", "avi","ogg","ogv","jpg","jpeg","png","gif"};
String fileNameTarget ="";
if ( ArrayUtils.contains( extAutorise, ext)) {
//Définir le fichier destination :
fileNameTarget = file.getOriginalFilename();
fileNameTarget = fileNameTarget.replaceAll(" ", "_");
File dir = storageLocation.toFile();
String serverFile = dir.getAbsolutePath() + File.separator + fileNameTarget ;
try {
try (InputStream is = file.getInputStream();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile))
) {
int i;
while ((i = is.read()) != -1) {
stream.write(i);
}
stream.flush();
}
} catch (IOException e) {
System.out.println("error : " + e.getMessage());
}
}
return fileNameTarget;
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
}
`
使用此代码,文件夹" upload-storage"是在项目的根目录创建的
视频已上传到此文件夹中...
但是在" videoForm.html"中,代码
<video id="video" th:src="'/upload-storage/'+${filename}" height="60"
autoplay="autoplay"></video>
什么都没有。 我有另一个解决方案 在StorageServiceImpl中,我使用代码:
private final String storageLocation = this.getClass().getResource("/static/").getPath();
取代:
private final Path storageLocation = Paths.get("upload-storage");
然后:
File dir = new File(storageLocation + File.separator + "upload-storage");
取代:
File dir = storageLocation.toFile();
然后:
File serverFile = new File(dir.getAbsolutePath() + File.separator + fileNameTarget);
取代:
String serverFile = dir.getAbsolutePath() + File.separator + fileNameTarget ;
使用此解决方案,将在目标文件夹中创建上传存储。
我使用其他控制器BaseController:
public class BaseController {
public static final String PARAM_BASE_URL = "baseURL";
public String getBaseURL(HttpServletRequest request){
return request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
}
}
` UploadController扩展了这个BaseController 我在recupereUpload()中添加了HttpServletRequest请求:
@PostMapping("/upload")
public String recupereUpload(@RequestParam("file") MultipartFile file,
Model model, HttpServletRequest request ){
我添加了recupereUpload发送的模型:
model.addAttribute(PARAM_BASE_URL, getBaseURL(request));
最后,我可以在videoForm.html中看到我的视频,代码为:
<video id="video" th:src="${baseURL}+'/upload-storage/'+${filename}" height="60" autoplay="autoplay"></video>
我可以关闭Tomcat,关闭Eclipse,关闭机器,然后再次打开:全部保留,我可以看到视频。
但是过了一段时间:一切都消失了
必须有一个更好的解决方案
你能救我吗?
答案 0 :(得分:0)
为什么不将Spring Content用于解决方案的视频内容部分?这样您就不需要实现任何视频内容处理。 Spring Content将为您提供此功能。要将Spring Content添加到项目中:
将Spring Content添加到类路径中。
的pom.xml
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.0.10</version>
</dependency>
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>content-fs-spring-boot-starter</artifactId>
<version>0.0.10</version>
</dependency>
将内容与您的视频实体相关联。
Video.java
@Entity
public class Video {
...
@ContentId
private String contentId;
@ContentLength
private Long contetLen;
@MimeType
private String mimeType;
...
设置“持久性文件夹”作为视频商店的根目录。这是存储/流式传输上传视频的地方。还要创建一个VideoStore
界面,以便向SC描述您希望如何关联内容。
SpringBootApplication.java
@SpringBootApplication
public class YourSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(YourSpringBootApplication.class, args);
}
@Configuration
@EnableFilesystemStores
public static class StoreConfig {
File filesystemRoot() {
return new File("/path/to/your/videos");
}
@Bean
public FileSystemResourceLoader fsResourceLoader() throws Exception {
return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
}
}
@StoreRestResource(path="videos")
public interface VideoStore extends ContentStore<Video,String> {
//
}
}
这就是在/videos
创建基于REST的视频服务所需的全部内容。本质上,当您的应用程序启动时,Spring Content将查看您的依赖项(查看Spring Content FS / REST),查看您的VideoStore
接口并根据文件系统注入该接口的实现。它还将注入一个控制器,该控制器也会将http请求转发给该实现。这样您就不必自己实施任何此类操作。
因此...
POST /videos/{video-entity-id}
会将视频存储在/path/to/your/videos
中,并将其与ID为video-entity-id
的视频实体相关联。
GET /videos/{video-entity-id}
将再次获取它。这支持部分内容请求或字节范围;即视频流。
依此类推......支持完整的CRUD。
有几个入门指南here。参考指南为here。还有一个教程视频here。编码位开始大约1/2通过。
HTH
答案 1 :(得分:0)
您是否通过在application.properties文件中添加以下属性来启用上传?
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
我写了一篇有关如何使用百里香在Spring Boot中上传多部分文件的文章。这是用于上传的服务。
package com.uploadMultipartfile.storage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
@Service
public class FileSystemStorageService implements StorageService
{
private final Path rootLocation;
@Autowired
public FileSystemStorageService(StorageProperties properties) {
this.rootLocation = Paths.get(properties.getUploadDir()).toAbsolutePath().normalize();
try {
Files.createDirectories(this.rootLocation);
} catch (Exception ex) {
throw new StorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
@Override
public String store(MultipartFile file)
{
// Normalize file name
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try
{
if (file.isEmpty())
{
throw new StorageException("Failed to store empty file " + file.getOriginalFilename());
}
// Copy file to the target location (Replacing existing file with the same name)
Path targetLocation = this.rootLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
return fileName;
}
catch (IOException e)
{
throw new StorageException("Failed to store file " + file.getOriginalFilename(), e);
}
}
@Override
public void init()
{
try
{
Files.createDirectory(rootLocation);
}
catch (IOException e)
{
throw new StorageException("Could not initialize storage", e);
}
}
}
这里是获取应用程序代码的链接。 http://mkaroune.e-monsite.com/pages/spring/spring-boot-multipart-file-upload.html