Skip to content

Instantly share code, notes, and snippets.

@pepoviola
Forked from eduardonunesp/exporter.rs
Created July 15, 2021 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pepoviola/b73b0d61d88f7b6c3b6cdec6ba94b4ed to your computer and use it in GitHub Desktop.
Save pepoviola/b73b0d61d88f7b6c3b6cdec6ba94b4ed to your computer and use it in GitHub Desktop.
pdf-exporter
use std::fs::File;
use std::io::{prelude::*, BufReader, Write};
use std::process::Command;
use actix_multipart::Multipart;
use actix_web::{
get, http::StatusCode, post, web, App, Error, HttpResponse, HttpServer, Responder,
};
use futures::{StreamExt, TryStreamExt};
use tempdir::TempDir;
#[get("/")]
async fn ping() -> impl Responder {
"Pong".with_status(StatusCode::OK)
}
#[post("/")]
async fn upload(mut payload: Multipart) -> Result<HttpResponse, Error> {
let dir = TempDir::new("temp")?;
let mut vec: Vec<u8> = vec![];
while let Ok(Some(mut field)) = payload.try_next().await {
let content_type = field.content_disposition().unwrap();
let filename = content_type.get_filename().unwrap();
let tmp_filepath = dir.path().join(sanitize_filename::sanitize(&filename));
let mut filepath = tmp_filepath.clone();
let mut f = web::block(move || std::fs::File::create(&tmp_filepath)).await?;
// Field in turn is stream of *Bytes* object
while let Some(chunk) = field.next().await {
let data = chunk?;
// filesystem operations are blocking, we have to use threadpool
f = web::block(move || f.write_all(&data).map(|_| f)).await?;
}
println!("{:?}", &filepath);
let mut soffice = Command::new("soffice");
let result = soffice
.arg("--headless")
.arg("--convert-to")
.arg("pdf")
.arg(&filepath)
.arg("--outdir")
.arg(std::path::Path::new(&filepath).parent().unwrap())
.output()?;
println!("{}", String::from_utf8_lossy(&result.stdout));
filepath.set_extension("pdf");
vec = web::block(move || {
let file = File::open(filepath)?;
let mut buf_reader = BufReader::new(file);
let mut tmp_vec: Vec<u8> = vec![];
buf_reader.read_to_end(&mut tmp_vec)?;
std::io::Result::Ok(tmp_vec)
})
.await?;
}
Ok(HttpResponse::Ok()
.content_type("application/pdf")
.body(vec)
.into())
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
let port = std::env::var("PORT").unwrap_or("3000".to_string());
let server_address = format!("0.0.0.0:{}", port);
println!("Serving on port {}", server_address);
HttpServer::new(|| App::new().service(upload).service(ping))
.bind(server_address)?
.run()
.await
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment