Skip to content

Commit 01e5b3f

Browse files
authored
upload video to lfs (#2138)
2 parents c0ec233 + 8b85cb6 commit 01e5b3f

12 files changed

Lines changed: 103 additions & 36 deletions

File tree

pom-dependency-tree.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ai.elimu:webapp:war:2.5.89-SNAPSHOT
1+
ai.elimu:webapp:war:2.5.91-SNAPSHOT
22
+- com.github.elimu-ai:model:jar:model-2.0.97:compile
33
| \- com.google.code.gson:gson:jar:2.13.0:compile
44
| \- com.google.errorprone:error_prone_annotations:jar:2.37.0:compile

src/main/java/ai/elimu/entity/content/multimedia/Video.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ai.elimu.model.v2.enums.content.VideoFormat;
44
import ai.elimu.util.GitHubLfsHelper;
5+
import ai.elimu.web.context.EnvironmentContextLoaderListener;
56
import jakarta.persistence.Column;
67
import jakarta.persistence.Entity;
78
import jakarta.persistence.EnumType;
@@ -45,4 +46,11 @@ public class Video extends Multimedia {
4546
@NotNull
4647
@Enumerated(EnumType.STRING)
4748
private VideoFormat videoFormat;
49+
50+
public String getUrl() {
51+
return "https://raw.githubusercontent.com/elimu-ai/webapp-lfs/main" +
52+
"/lang-" + EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language") +
53+
"/videos" +
54+
"/" + getChecksumMd5() + "." + getVideoFormat().toString().toLowerCase();
55+
}
4856
}

src/main/java/ai/elimu/rest/v2/JpaToGsonConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ public static VideoGson getVideoGson(Video video) {
353353
videoGson.setTitle(video.getTitle());
354354
videoGson.setVideoFormat(video.getVideoFormat());
355355
videoGson.setChecksumMd5(video.getChecksumMd5());
356-
videoGson.setFileUrl("/video/" + video.getId() + "_r" + video.getRevisionNumber() + "." + video.getVideoFormat().toString().toLowerCase());
356+
videoGson.setFileUrl(video.getUrl());
357357
videoGson.setFileSize(video.getBytes().length / 1024);
358358
videoGson.setThumbnailUrl("/video/" + video.getId() + "_r" + video.getRevisionNumber() + "_thumbnail.png");
359359
Set<WordGson> wordGsons = new HashSet<>();

src/main/java/ai/elimu/util/GitHubLfsHelper.java

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.google.gson.JsonParser;
88

99
import ai.elimu.entity.content.multimedia.Image;
10+
import ai.elimu.entity.content.multimedia.Video;
1011
import ai.elimu.web.context.EnvironmentContextLoaderListener;
1112
import kong.unirest.core.HttpResponse;
1213
import kong.unirest.core.Unirest;
@@ -19,32 +20,64 @@
1920
@Slf4j
2021
public class GitHubLfsHelper {
2122

23+
private static final String API_BASE_URL = "https://api.github.com/repos/elimu-ai/webapp-lfs/contents/";
24+
2225
/**
23-
* Upload file to LFS.
26+
* Upload image to LFS.
2427
*
2528
* @param image The Image representing the file bytes.
2629
* @param bytes The file bytes to be stored.
27-
* @return The hash (CID) generated by GitHub.
30+
* @return The checksum (SHA) generated by GitHub.
2831
*/
2932
public static String uploadImageToLfs(Image image, byte[] bytes) {
3033
log.info("uploadImageToLfs");
3134

32-
// Store file in webapp-lfs
33-
// https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents
34-
3535
String languageCode = EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language");
3636
log.info("languageCode: " + languageCode);
3737

3838
String filename = image.getId() + "_r" + image.getRevisionNumber() + "." + image.getImageFormat().toString().toLowerCase();
3939
log.info("filename: " + filename);
40+
41+
String path = "lang-" + languageCode + "/images/" + filename;
42+
log.info("path: " + path);
4043

41-
String url = "https://api.github.com/repos/elimu-ai/webapp-lfs/contents/" +
42-
"lang-" + languageCode + "/" +
43-
"images/" + filename;
44-
log.info("url: " + url);
44+
return uploadFileToLfs(path, bytes);
45+
}
46+
47+
/**
48+
* Upload video to LFS.
49+
*
50+
* @param video The Video representing the file bytes.
51+
* @param bytes The file bytes to be stored.
52+
* @return The checksum (SHA) generated by GitHub.
53+
*/
54+
public static String uploadVideoToLfs(Video video, byte[] bytes) {
55+
log.info("uploadVideoToLfs");
56+
57+
String languageCode = EnvironmentContextLoaderListener.PROPERTIES.getProperty("content.language");
58+
log.info("languageCode: " + languageCode);
59+
60+
String filename = video.getChecksumMd5() + "." + video.getVideoFormat().toString().toLowerCase();
61+
log.info("filename: " + filename);
62+
63+
String path = "lang-" + languageCode + "/videos/" + filename;
64+
log.info("path: " + path);
4565

66+
return uploadFileToLfs(path, bytes);
67+
}
68+
69+
/**
70+
* Store file in webapp-lfs
71+
* https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents
72+
*/
73+
private static String uploadFileToLfs(String path, byte[] bytes) {
74+
log.info("uploadFileToLfs");
75+
76+
String url = API_BASE_URL + path;
77+
log.info("url: " + url);
78+
4679
JsonObject body = new JsonObject();
47-
body.addProperty("message", "chore(images): add " + filename);
80+
body.addProperty("message", "chore: add " + path );
4881
body.addProperty("content", Base64.getEncoder().encodeToString(bytes));
4982

5083
JsonObject committer = new JsonObject();

src/main/java/ai/elimu/web/content/multimedia/video/VideoCreateController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import ai.elimu.model.v2.enums.content.LiteracySkill;
77
import ai.elimu.model.v2.enums.content.NumeracySkill;
88
import ai.elimu.model.v2.enums.content.VideoFormat;
9+
import ai.elimu.util.ChecksumHelper;
10+
import ai.elimu.util.GitHubLfsHelper;
911
import jakarta.servlet.ServletException;
1012
import jakarta.servlet.http.HttpServletRequest;
1113
import java.io.IOException;
@@ -88,6 +90,8 @@ public String handleSubmit(
8890
video.setContentType(contentType);
8991

9092
video.setBytes(bytes);
93+
video.setChecksumMd5(ChecksumHelper.calculateMD5(bytes));
94+
// TODO: https://github.com/elimu-ai/webapp/issues/2137
9195

9296
// TODO: convert to a default video format?
9397
}
@@ -118,9 +122,13 @@ public String handleSubmit(
118122
return "content/multimedia/video/create";
119123
} else {
120124
video.setTitle(video.getTitle().toLowerCase());
125+
String checksumGitHub = GitHubLfsHelper.uploadVideoToLfs(video, video.getBytes());
126+
video.setChecksumGitHub(checksumGitHub);
121127
video.setTimeLastUpdate(Calendar.getInstance());
122128
videoDao.create(video);
123129

130+
// TODO: https://github.com/elimu-ai/webapp/issues/1545
131+
124132
return "redirect:/content/multimedia/video/list#" + video.getId();
125133
}
126134
}

src/main/java/ai/elimu/web/content/multimedia/video/VideoCsvExportController.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,13 @@ public void handleRequest(
3232
List<Video> videos = videoDao.readAllOrderedById();
3333
log.info("videos.size(): " + videos.size());
3434
for (Video video : videos) {
35-
String fileUrl = "/video/" + video.getId() + "." + video.getVideoFormat().toString().toLowerCase();
3635
csvFileContent += video.getId() + ","
3736
+ video.getContentType() + ","
3837
+ video.getContentLicense() + ","
3938
+ "\"" + video.getAttributionUrl() + "\","
4039
+ "\"" + video.getTitle() + "\","
4140
+ "\"" + video.getChecksumMd5() + "\","
42-
+ "\"" + fileUrl + "\","
41+
+ "\"" + video.getUrl() + "\","
4342
+ video.getVideoFormat() + "\n";
4443
}
4544

src/main/java/ai/elimu/web/content/multimedia/video/VideoEditController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import ai.elimu.model.v2.enums.content.LiteracySkill;
1515
import ai.elimu.model.v2.enums.content.NumeracySkill;
1616
import ai.elimu.model.v2.enums.content.VideoFormat;
17+
import ai.elimu.util.ChecksumHelper;
18+
import ai.elimu.util.GitHubLfsHelper;
1719
import jakarta.servlet.ServletException;
1820
import jakarta.servlet.http.HttpServletRequest;
1921
import java.io.IOException;
@@ -63,6 +65,14 @@ public String handleRequest(
6365
log.info("handleRequest");
6466

6567
Video video = videoDao.read(id);
68+
if (StringUtils.isBlank(video.getChecksumGitHub())) {
69+
String checksumGitHub = GitHubLfsHelper.uploadVideoToLfs(video, video.getBytes());
70+
video.setChecksumGitHub(checksumGitHub);
71+
video.setRevisionNumber(video.getRevisionNumber() + 1);
72+
videoDao.update(video);
73+
74+
// TODO: https://github.com/elimu-ai/webapp/issues/1545
75+
}
6676
model.addAttribute("video", video);
6777

6878
model.addAttribute("contentLicenses", ContentLicense.values());
@@ -116,6 +126,8 @@ public String handleSubmit(
116126
video.setContentType(contentType);
117127

118128
video.setBytes(bytes);
129+
video.setChecksumMd5(ChecksumHelper.calculateMD5(bytes));
130+
// TODO: https://github.com/elimu-ai/webapp/issues/2137
119131

120132
// TODO: convert to a default video format?
121133
}
@@ -140,6 +152,8 @@ public String handleSubmit(
140152
video.setRevisionNumber(video.getRevisionNumber() + 1);
141153
videoDao.update(video);
142154

155+
// TODO: https://github.com/elimu-ai/webapp/issues/1545
156+
143157
return "redirect:/content/multimedia/video/list#" + video.getId();
144158
}
145159
}

src/main/webapp/WEB-INF/jsp/content/multimedia/image/create.jsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
<div class="file-field input-field col s12">
8282
<div class="btn">
8383
<span>File</span>
84-
<form:input path="bytes" type="file" />
84+
<input name="bytes" type="file" />
8585
</div>
8686
<div class="file-path-wrapper">
8787
<input class="file-path validate" type="text" />

src/main/webapp/WEB-INF/jsp/content/multimedia/image/edit.jsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
<div class="file-field input-field col s12">
101101
<div class="btn">
102102
<span>File</span>
103-
<form:input path="bytes" type="file" />
103+
<input name="bytes" type="file" />
104104
</div>
105105
<div class="file-path-wrapper">
106106
<input class="file-path validate" type="text" />

src/main/webapp/WEB-INF/jsp/content/multimedia/video/edit.jsp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
<content:section cssId="videoEditPage">
66
<h4><content:gettitle /></h4>
7-
<div class="card-panel">
7+
<div class="card-panel cid-${video.checksumGitHub != null}">
8+
<video poster="<spring:url value='/video/${video.id}_r${video.revisionNumber}_thumbnail.png' />" controls>
9+
<source src="<spring:url value='${video.url}' />" />
10+
</video>
11+
812
<form:form modelAttribute="video" enctype="multipart/form-data">
913
<tag:formErrors modelAttribute="video" />
1014

@@ -112,19 +116,6 @@
112116
</content:section>
113117

114118
<content:aside>
115-
<h5 class="center">Preview</h5>
116-
117-
<div class="video card">
118-
<a class="valign-wrapper" href="<spring:url value='/video/${video.id}_r${video.revisionNumber}.${fn:toLowerCase(video.videoFormat)}' />" target="_blank">
119-
<div style="position: absolute; width: 100%; text-align: center;">
120-
<i class="material-icons" style=" background-color: rgba(0,0,0, 0.2); color: rgba(255,255,255, 0.8); padding: 0.5rem; font-size: 3em; border-width: 2px; border-color: rgba(255,255,255, 0.8); border-style: solid; border-radius: 50%;">play_arrow</i>
121-
</div>
122-
<img src="<spring:url value='/video/${video.id}_r${video.revisionNumber}_thumbnail.png' />" alt="${video.title}" />
123-
</a>
124-
</div>
125-
126-
<div class="divider" style="margin-top: 1em;"></div>
127-
128119
<h5 class="center">Content labels</h5>
129120

130121
<b>Letters</b><br />
@@ -364,4 +355,17 @@
364355
});
365356
});
366357
</script>
358+
359+
<div class="divider" style="margin-bottom: 1em;"></div>
360+
361+
<label>checksum_md5</label>
362+
<code>${video.checksumMd5}</code><br />
363+
<br />
364+
365+
<label>file_url</label>
366+
<code>${video.url}</code><br />
367+
<br />
368+
369+
<label>checksum_github</label>
370+
<code>${video.checksumGitHub}</code><br />
367371
</content:aside>

0 commit comments

Comments
 (0)