我工作的一个项目,以获得从视频缩略图,然后在主页上显示它们。
缩略图是在文件夹上传中正确生成的,但是未显示在主页中。我找不到错误404。
Bellow是JeutrollServiceImp的代码,用于从视频中获取缩略图 在HTML中,我使用的图象的一硬编码名称为测试的purprose。
import com.jeutroll.dao.UserRepository;
import com.jeutroll.dao.VideoRepository;
import com.jeutroll.entities.Video;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
@Service
@Transactional
public class JeutrollServiceImp implements JeutrollService
{
public static String uploadDirectory= System.getProperty("user.home") + "/uploads";
@Autowired
private UserRepository userRepository;
@Autowired
private VideoRepository videoRepository;
@Override
public Page<Video> browseVideos(String aInCategory, int page, int size)
{
return videoRepository.listVideos(aInCategory, new PageRequest(page, size));
}
@Override
public Video browseVideo(String aTitle)
{
return null;
}
@Override
public void uploadVideo(Video aInVideo)
{
}
@Override
public com.jeutroll.entities.User findUserByEmail(String email)
{
return userRepository.findByEmail(email);
}
@Override
public String retriveThumbnailFromVideo(String videoPath)
{
String thumbnailPath;
File lImgFile = null;
FFmpegFrameGrabber g = new FFmpegFrameGrabber(videoPath);
try
{
g.start();
// on fait défiler les 10 premières frame
for (int i = 0; i < 100; i++)
{
g.grab();
}
Frame lFrame = g.grabImage();
BufferedImage lBufferedImage = new Java2DFrameConverter().convert(lFrame);
// on enregistre la 101ième
Path path = Paths.get(uploadDirectory,"life_" + System.currentTimeMillis() + ".png" );
//lImgFile = new File("/resources/static/life_" + System.currentTimeMillis() + ".png");
lImgFile = new File(path.toString());
ImageIO.write(lBufferedImage, "png", lImgFile);
// récupération de la durée de la vidéo
float duration = (float) g.getLengthInTime() / 1000000;
g.stop();
}
catch (Exception e)
{
// TODO Auto-generated catch block
System.err
.println("La création de la miniature n'a pas pu être effectuée!");
e.printStackTrace();
}
return lImgFile.getName();
}
@Override
public void uploadVideos(String aInFilePath)
{
// storageService.store(file);
}
}
WebConfigurer类别
package com.jeutroll.configuration;
import com.jeutroll.service.JeutrollServiceImp;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
public class WebConfigurer extends WebMvcConfigurerAdapter {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/uploads/**").addResourceLocations("file:/" + JeutrollServiceImp.uploadDirectory);
}
}
这里我使用的是磁盘上外部文件夹中已经存在的视频。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="template1.html">
<head>
<meta charset="UTF-8">
<title>Jeutroll</title>
</head>
<body>
<div layout:fragment="content">
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2 text-center">
<h2 class="section-title uppercase"> Projets Réalisés</h2>
</div>
</div>
<section class="row" th:if="${videos}">
<div class="col-xs-12 col-sm-3 col-md-4 col-lg-4" th:each="v:${videos}">
<a href="#" class="thumbnail"><img src="/uploads/life_1549107645227.png" alt="Image 2" width="500px " >
<div class="caption">
<span class="cat-link">categorie</span>
<span class="separator">|</span>
<span class="pub-date">6 janvier 2019</span>
<span class="glyphicon glyphicon-comment"></span>
</div>
<div class="rating">
</div>
</a>
</div>
</section>
</div>
</div>
</body>
</html>
答案 0 :(得分:0)
在这个问题上停留了几个小时之后,我终于弄明白了。主要问题是我没有在WebConfigurer类中添加@EnableWebMvc。第二个是映像目录不正确。我正在Windows OS上执行我的项目,并且使用了System.getProperty(“ user.home”)+“ / uploads”;代替 System.getProperty(“ user.home”)+“ \ uploads”;
因为它是经常性的主题。我决定为这种情况写一个例子。我回家会有所帮助。 http://mkaroune.e-monsite.com/pages/spring/get-images-from-external-folder-on-disk.html
@Ahmed是,该方法返回正确的图像路径。
答案 1 :(得分:0)
我建议您看看Spring Content。通过该社区项目,您可以使用相同的编程模型将内容(例如视频之类的非结构化数据)与Spring数据实体相关联。
添加到现有项目中非常简单,它会为您提供与Spring Data相同的简单编程模型,存储的抽象(因此它可以存储在Spring Content支持的任何Storage中)以及许多其他功能具有OOTB之类的功能,例如支持视频流的REST端点。
如果您对这里感兴趣的话,我想您可以这样做(假设使用Spring Boot)。
将依赖项添加到您的项目中:-
pom.xml
<!-- Java API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-fs-boot-starter</artifactId>
<version>0.5.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>com.github.paulcwarren</groupId>
<artifactId>spring-content-rest-boot-starter</artifactId>
<version>0.5.0</version>
</dependency>
配置文件存储:
StoreConfig.java
@Configuration
@EnableFilesystemStores
public class EnableFilesystemStoresConfig {
@Bean
File filesystemRoot() {
try {
return new File(JeutrollServiceImp.uploadDirectory);
} catch (IOException ioe) {}
return null;
}
@Bean
FileSystemResourceLoader fileSystemResourceLoader() {
return new FileSystemResourceLoader(filesystemRoot().getAbsolutePath());
}
}
将内容与您的实体相关联:
@Entity
public class Video {
@Id @GeneratedValue
private Long id;
... other Spring Data fields ...
// associate the video
@ContentId
private UUID contentId;
@ContentLength
private Long contentLength;
@Mimetype
private String mimeType;
// associate thumbnails
private Thumbnail thumbnail;
...
}
@Entity
public class Thumbnail {
@ContentId
private UUID contentId;
@ContentLength
private Long contentLength;
@MimeType
private String mimeType;
}
创建视频存储和缩略图存储:
VideoStore.java/ThumbnailStore.java
@StoreRestResource(path="videoContent")
public interface VideoStore extends ContentStore<Video,UUID> {
}
public interface ThumbnailStore extends ContentStore<Thumbnail,UUID> {
}
spring-content-fs-boot-starter
依赖项将导致Spring Content注入基于文件系统的实现,因此您无需担心自己实现这些。而且,spring-content-rest
依赖关系将导致Spring Content也注入@Controller
的实现,这些实现分别将HTTP请求转发到VideoStore
和ThumbnailStore
的方法上。
因此,您现在可以在/videoContent
处使用基于REST的全功能(POST,PUT,GET,DELETE)视频服务,该服务将使用您的VideoStore
来检索(和存储){{ 1}}在您的服务器上。
所以:
JeutrollServiceImp.uploadDirectory
将上传POST /videoContent/ -F "image=@/some/path/to/a/video.mp4"
并将其添加到您的上传目录中。
video.mp4
将再次获取它并存储其余端点支持Range请求,因此HTML5视频控件将正常运行。
对于缩略图,您可以添加处理以生成缩略图并将其存储在带注释的存储事件处理程序中:-
GET /videoContent/{videoId}
每个视频存储后,其缩略图将通过以下方式提供:
@Configuration
public class ThumbnailConfig {
@Bean
public StoreEventHandler thumbnailEventHandler() {
return new ThumbnailEventHandler();
}
@StoreEventHandler
public static class ThumbnailEventHandler {
@Autowired
VideoRepository videoRepository;
@Autowired
VideoStore videoStore;
@Autowired
ThumbnailStore thumnailStore;
@HandleAfterSetContent
public void handleAfterSetContent(Video video) {
BufferedImage img = // use modfied retrieveThumbnailFromVideo(videoStore.getContent(video));
Thumbnail thumbnail = new Thumbnail();
thumbnail.setMimeType("png")
thumbnail.setContent(thumbnail, toInputStream(img))
video.setThumbnail(thumbnail)
videoRepository.save(video);
}
}
}
或:
GET /videoContent/{videoId}/thumbnail
在存储模仿类型时,这些URL将在您HTML的标准中用作GET /videoContent/{videoId}/thumbnail/{contentId}
。
所以:
成为:
HTH