Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for ebooks #63

Merged
merged 14 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Install linux dependencies
run: |
sudo apt-get update && sudo apt-get upgrade
sudo apt-get -y install libreoffice
sudo apt-get -y install libreoffice calibre
- name: Setup ffmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
id: setup-ffmpeg
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ FROM debian:trixie-slim AS release
WORKDIR /

RUN apt-get update \
&& apt-get install -y --no-install-recommends default-jre libreoffice libreoffice-java-common ffmpeg \
&& apt-get install -y --no-install-recommends default-jre libreoffice libreoffice-java-common ffmpeg calibre \
&& apt-get autoremove -y \
&& apt-get purge -y --auto-remove \
&& rm -rf /var/lib/apt/lists/*
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,5 +109,29 @@ A modal will pop up with a preview of the converted image.
| CSV | | | ✅ | |
| XLSX | | | | ✅ |

## Ebooks X Ebooks

| | MOBI | EPUB |
| ---- | ---- | --- |
| EPUB | ✅ | |
| MOBI | | ✅ |


## Documents X Ebooks

| | EPUB | MOBI |
| ---- | ---- | --- |
| PDF | ✅ | ✅ |
| DOCX | | |
| CSV | | |
| XLSX | | |

## Ebooks X Documents

| | PDF |
| ---- | ---- |
| EPUB | ✅ |
| MOBI | ✅ |

## License
The MIT License (MIT). See [LICENSE](LICENSE) file for more details.
20 changes: 16 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,50 +136,60 @@ func handleUploadFile(w http.ResponseWriter, r *http.Request) error {
err error
)

// parse and validate file and post parameters.
// Parse and validate file and post parameters.
file, fileHeader, err := r.FormFile(uploadFileFormField)
if err != nil {
log.Printf("error ocurred getting file from form: %v", err)
return WithHTTPStatus(err, http.StatusBadRequest)
}
defer file.Close()

// Get the content of the file in form of a slice of bytes.
fileBytes, err := io.ReadAll(file)
if err != nil {
log.Printf("error ocurred reading file: %v", err)
return WithHTTPStatus(err, http.StatusBadRequest)
}

// Get the sub-type of the input file from the form.
targetFileSubType := r.FormValue("input_format")

// Call Detect fuction to get the mimetype of the input file.
detectedFileType := mimetype.Detect(fileBytes)

// Parse the mimetype to get the type and the sub-type of the input file.
fileType, subType, err := files.TypeAndSupType(detectedFileType.String())
if err != nil {
log.Printf("error occurred getting type and subtype from mimetype: %v", err)
return WithHTTPStatus(err, http.StatusBadRequest)
}

// Get the right factory based off the input file type.
fileFactory, err := files.BuildFactory(fileType, fileHeader.Filename)
if err != nil {
log.Printf("error occurred while getting a file factory: %v", err)
return WithHTTPStatus(err, http.StatusBadRequest)
}

// Returns an object that implements the File interface based on the sub-type of the input file.
f, err := fileFactory.NewFile(subType)
if err != nil {
log.Printf("error occurred getting the file object: %v", err)
return WithHTTPStatus(err, http.StatusBadRequest)
}

// Return the kind of the output file.
targetFileType := files.SupportedFileTypes()[targetFileSubType]

// Convert the file to the target format.
// convertedFile is an io.Reader.
convertedFile, err = f.ConvertTo(
cases.Title(language.English).String(targetFileType),
targetFileSubType,
bytes.NewReader(fileBytes),
)
if err != nil {
log.Printf("error ocurred while converting image %v", err)
log.Printf("error ocurred while processing the input file: %v", err)
return WithHTTPStatus(err, http.StatusInternalServerError)
}

Expand All @@ -193,18 +203,20 @@ func handleUploadFile(w http.ResponseWriter, r *http.Request) error {

newFile, err := os.Create(convertedFilePath)
if err != nil {
log.Printf("error occurred converting file: %v", err)
log.Printf("error occurred while creating the output file: %v", err)
return WithHTTPStatus(err, http.StatusInternalServerError)
}
defer newFile.Close()

buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(convertedFile); err != nil {
log.Printf("error occurred while readinf from the converted file: %v", err)
return WithHTTPStatus(err, http.StatusInternalServerError)
}

convertedFileBytes := buf.Bytes()
if _, err := newFile.Write(convertedFileBytes); err != nil {
log.Printf("error occurred writing file: %v", err)
log.Printf("error occurred writing converted output to a file in disk: %v", err)
return WithHTTPStatus(err, http.StatusInternalServerError)
}

Expand Down
7 changes: 6 additions & 1 deletion pkg/files/document_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/danvergara/morphos/pkg/files/documents"
"github.com/danvergara/morphos/pkg/files/ebooks"
)

// DocumentFactory implements the FileFactory interface.
Expand All @@ -28,7 +29,11 @@ func (d *DocumentFactory) NewFile(f string) (File, error) {
return documents.NewXlsx(d.filename), nil
case documents.CSV:
return documents.NewCsv(d.filename), nil
case ebooks.EpubMimeType, ebooks.EPUB:
return ebooks.NewEpub(d.filename), nil
case ebooks.MobiMimeType, ebooks.MOBI:
return ebooks.NewMobi(d.filename), nil
default:
return nil, fmt.Errorf("type file file %s not recognized", f)
return nil, fmt.Errorf("type file %s not recognized", f)
}
}
14 changes: 11 additions & 3 deletions pkg/files/documents/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ func (c *Csv) ConvertTo(fileType, subType string, file io.Reader) (io.Reader, er

reader := csv.NewReader(file)
xlsxFile := xlsx.NewFile()
sheet, err := xlsxFile.AddSheet(strings.TrimSuffix(c.filename, filepath.Ext(c.filename)))
sheet, err := xlsxFile.AddSheet(
strings.TrimSuffix(c.filename, filepath.Ext(c.filename)),
)
if err != nil {
return nil, fmt.Errorf("error creating a xlsx sheet %w", err)
}
Expand All @@ -100,7 +102,12 @@ func (c *Csv) ConvertTo(fileType, subType string, file io.Reader) (io.Reader, er
}
}

xlsxFile.Save(xlsxPath)
if err := xlsxFile.Save(xlsxPath); err != nil {
return nil, fmt.Errorf(
"error at saving the temporary csv file: %w",
err,
)
}

tmpCsvFile, err := os.Open(xlsxPath)
if err != nil {
Expand All @@ -109,7 +116,7 @@ func (c *Csv) ConvertTo(fileType, subType string, file io.Reader) (io.Reader, er
err,
)
}
defer tmpCsvFile.Close()
defer os.Remove(tmpCsvFile.Name())

// Creates the zip file that will be returned.
archive, err := os.Create(zipFileName)
Expand All @@ -119,6 +126,7 @@ func (c *Csv) ConvertTo(fileType, subType string, file io.Reader) (io.Reader, er
err,
)
}
defer os.Remove(archive.Name())

// Creates a Zip Writer to add files later on.
zipWriter := zip.NewWriter(archive)
Expand Down
8 changes: 8 additions & 0 deletions pkg/files/documents/documents.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ const (
XLSX = "xlsx"
XLSXMIMEType = "vnd.openxmlformats-officedocument.spreadsheetml.sheet"

EpubMimeType = "epub+zip"
EPUB = "epub"

MOBI = "mobi"
MobiMimeType = "x-mobipocket-ebook"

imageMimeType = "image/"
imageType = "image"

documentMimeType = "application/"
tesxtMimeType = "text/"
documentType = "document"

ebookType = "ebook"
)
26 changes: 26 additions & 0 deletions pkg/files/documents/documents_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,32 @@ func TestPDFTConvertTo(t *testing.T) {
input input
expected expected
}{
{
name: "pdf to mobi",
input: input{
filename: "testdata/bitcoin.pdf",
mimetype: "application/pdf",
targetFileType: "Ebook",
targetFormat: "mobi",
documenter: documents.NewPdf("bitcoin.pdf"),
},
expected: expected{
mimetype: "application/zip",
},
},
{
name: "pdf to epub",
input: input{
filename: "testdata/bitcoin.pdf",
mimetype: "application/pdf",
targetFileType: "Ebook",
targetFormat: "epub",
documenter: documents.NewPdf("bitcoin.pdf"),
},
expected: expected{
mimetype: "application/zip",
},
},
{
name: "pdf to jpeg",
input: input{
Expand Down
Loading
Loading