Skip to content

Commit cba5109

Browse files
committed
add imagemagick
1 parent faee0ca commit cba5109

5 files changed

Lines changed: 89 additions & 19 deletions

File tree

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ RUN apk add --no-cache \
99
--repository http://dl-cdn.alpinelinux.org/alpine/edge/main \
1010
gperftools-dev
1111
RUN apk add --no-cache nss freetype harfbuzz ttf-freefont
12-
RUN apk add openjdk8-jre
12+
RUN apk add openjdk8-jre imagemagick ghostscript
13+
RUN sed -i 's/rights="none" pattern="PDF"/rights="read|write" pattern="PDF"/' /etc/ImageMagick-6/policy.xml
1314

1415
## INITIAL BUILDER
1516
FROM rust:1.91-alpine3.22 AS builder

src/upload/imagemagick.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::{error::Error, path::PathBuf, process::Stdio};
2+
3+
use tokio::process::Command;
4+
5+
use crate::{
6+
common::{constant::TMP_FS_PATH, util::IdGenerator},
7+
upload::ConvertType,
8+
};
9+
10+
pub async fn convert_to(
11+
input_path: impl Into<PathBuf>,
12+
ct: ConvertType,
13+
) -> Result<Vec<u8>, Box<dyn Error>> {
14+
let extension = ct.to_str();
15+
let input_path: PathBuf = input_path.into();
16+
tracing::debug!("convert file {input_path:?}");
17+
let input_path_str = &input_path.display().to_string();
18+
let temp_dir = TMP_FS_PATH.join(IdGenerator.get());
19+
tokio::fs::create_dir_all(&temp_dir).await?;
20+
let output = Command::new("convert")
21+
.args([input_path_str, &format!("{extension}:-")])
22+
.stdout(Stdio::piped())
23+
.stderr(Stdio::piped())
24+
.output()
25+
.await?;
26+
if output.status.success() {
27+
let input_path = input_path.with_extension(extension);
28+
let input_path = input_path
29+
.file_name()
30+
.ok_or("no file name")?
31+
.to_string_lossy();
32+
let path = format!("{}/{input_path}", temp_dir.display());
33+
let bytes = tokio::fs::read(&path).await?;
34+
tokio::spawn(async move {
35+
if let Err(e) = tokio::fs::remove_dir_all(&temp_dir).await {
36+
tracing::error!("could not remove temp thumb {e}");
37+
}
38+
});
39+
Ok(bytes)
40+
} else {
41+
Err(format!(
42+
"error! stdout: {}\nstderr: {}",
43+
String::from_utf8_lossy(&output.stdout),
44+
String::from_utf8_lossy(&output.stderr),
45+
)
46+
.into())
47+
}
48+
}

src/upload/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
pub mod domain;
2+
pub mod imagemagick;
23
pub mod routes;
34
pub mod service;
45
pub mod soffice;
6+
7+
pub enum ConvertType {
8+
Png,
9+
// Pdf,
10+
}
11+
impl ConvertType {
12+
fn to_str(&self) -> &str {
13+
match self {
14+
ConvertType::Png => "png",
15+
// ConvertType::Pdf => "pdf",
16+
}
17+
}
18+
}

src/upload/service.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ use tokio::{
1717
use tokio_util::io::StreamReader;
1818
use tracing::debug;
1919

20+
use crate::upload::ConvertType;
2021
use crate::{
2122
common::{
2223
constant::{SHARE_DRIVE_PATH_BUF, THUMB_H, THUMB_W, TMP_FS_PATH},
2324
domain::ServiceError,
2425
util::{IdGenerator, StoreCollection},
2526
},
2627
store::{Repository, StoreClient, StoreRepository, get_document_filter_by_maybe_object_id},
27-
upload::soffice::{ConvertType, convert_to},
2828
};
2929

3030
use super::domain::FileUploadV2;
@@ -88,7 +88,7 @@ impl FileService {
8888
.map_err(ServiceError::new)
8989
.map(|im| (upl.content_type.clone(), im))
9090
} else {
91-
match convert_to(temp_file_path, ConvertType::Png)
91+
match super::imagemagick::convert_to(temp_file_path, ConvertType::Png)
9292
.await
9393
.map_err(ServiceError::new)
9494
.map(|bytes| {
@@ -99,11 +99,28 @@ impl FileService {
9999
Ok(img) => img,
100100
Err(e) => {
101101
tracing::error!(
102-
"error converting file {}: {}, giving up...",
102+
"error converting file {}: {}, trying with soffice...",
103103
internal_name,
104104
e
105105
);
106-
return Ok(None);
106+
match super::soffice::convert_to(temp_file_path, ConvertType::Png)
107+
.await
108+
.map_err(ServiceError::new)
109+
.map(|bytes| {
110+
image::load_from_memory(&bytes)
111+
.map_err(ServiceError::new)
112+
.map(|im| (Some(IMAGE_PNG.to_string()), im))
113+
}) {
114+
Ok(img) => img,
115+
Err(e) => {
116+
tracing::error!(
117+
"error converting file {}: {}, giving up...",
118+
internal_name,
119+
e
120+
);
121+
return Ok(None);
122+
}
123+
}
107124
}
108125
}
109126
}?;

src/upload/soffice.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use std::{error::Error, path::PathBuf, process::Stdio};
22

33
use tokio::process::Command;
44

5-
use crate::common::{constant::TMP_FS_PATH, util::IdGenerator};
5+
use crate::{
6+
common::{constant::TMP_FS_PATH, util::IdGenerator},
7+
upload::ConvertType,
8+
};
69

710
pub async fn convert_to(
811
input_path: impl Into<PathBuf>,
@@ -49,16 +52,3 @@ pub async fn convert_to(
4952
.into())
5053
}
5154
}
52-
53-
pub enum ConvertType {
54-
Png,
55-
// Pdf,
56-
}
57-
impl ConvertType {
58-
fn to_str(&self) -> &str {
59-
match self {
60-
ConvertType::Png => "png",
61-
// ConvertType::Pdf => "pdf",
62-
}
63-
}
64-
}

0 commit comments

Comments
 (0)