1
0
mirror of https://github.com/Stirling-Tools/Stirling-PDF.git synced 2024-11-16 12:20:12 +01:00

starting issue, implementing pdf-to-csv view

This commit is contained in:
Atrem Petrenko 2023-10-31 18:58:40 +01:00
parent 18c5f5bb2b
commit d6afb07533
7 changed files with 293 additions and 233 deletions

View File

@ -81,10 +81,12 @@ dependencies {
// https://mvnrepository.com/artifact/org.apache.pdfbox/jbig2-imageio // https://mvnrepository.com/artifact/org.apache.pdfbox/jbig2-imageio
implementation group: 'org.apache.pdfbox', name: 'jbig2-imageio', version: '3.0.4' implementation group: 'org.apache.pdfbox', name: 'jbig2-imageio', version: '3.0.4'
implementation 'commons-io:commons-io:2.13.0' implementation 'commons-io:commons-io:2.13.0'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
//general PDF //general PDF
// https://mvnrepository.com/artifact/com.opencsv/opencsv
implementation group: 'com.opencsv', name: 'opencsv', version: '5.7.1'
implementation 'org.apache.pdfbox:pdfbox:2.0.29' implementation 'org.apache.pdfbox:pdfbox:2.0.29'
implementation 'org.apache.pdfbox:xmpbox:2.0.29' implementation 'org.apache.pdfbox:xmpbox:2.0.29'
implementation 'org.bouncycastle:bcprov-jdk15on:1.70' implementation 'org.bouncycastle:bcprov-jdk15on:1.70'
@ -101,8 +103,16 @@ dependencies {
compileOnly 'org.projectlombok:lombok:1.18.28' compileOnly 'org.projectlombok:lombok:1.18.28'
annotationProcessor 'org.projectlombok:lombok:1.18.28' annotationProcessor 'org.projectlombok:lombok:1.18.28'
//// https://mvnrepository.com/artifact/technology.tabula/tabula
// implementation group: 'technology.tabula', name: 'tabula', version: '1.0.5'
// implementation files('/Users/artempetrenko/Java/Stirling-PDF/tabula-1.0.5-jar-with-dependencies.jar')
implementation fileTree(include: ['tabula-1.0.5-jar-with-dependencies.jar'],dir: 'libs')
} }
task writeVersion { task writeVersion {
def propsFile = file('src/main/resources/version.properties') def propsFile = file('src/main/resources/version.properties')
def props = new Properties() def props = new Properties()

View File

@ -99,6 +99,14 @@ public class ConverterWebController {
return modelAndView; return modelAndView;
} }
@GetMapping("/pdf-to-csv")
@Hidden
public ModelAndView pdfToCSV() {
ModelAndView modelAndView = new ModelAndView("convert/pdf-to-csv");
modelAndView.addObject("currentPage", "pdf-to-csv");
return modelAndView;
}
@GetMapping("/pdf-to-pdfa") @GetMapping("/pdf-to-pdfa")
@Hidden @Hidden

View File

@ -93,7 +93,6 @@ account.accountSettings=Account Settings
account.adminSettings=Admin Settings - View and Add Users account.adminSettings=Admin Settings - View and Add Users
account.userControlSettings=User Control Settings account.userControlSettings=User Control Settings
account.changeUsername=Change Username account.changeUsername=Change Username
account.changeUsername=Change Username
account.password=Confirmation Password account.password=Confirmation Password
account.oldPassword=Old password account.oldPassword=Old password
account.newPassword=New Password account.newPassword=New Password
@ -334,7 +333,12 @@ showJS.tags=JS
home.autoRedact.title=Auto Redact home.autoRedact.title=Auto Redact
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
showJS.tags=JS autoRedact.tags=JS
home.tableExtraxt.title=Table Extraction
home.tableExtraxt.desc=Table Extraction from PDF to CSV
tableExtraxt.tags=CSV
########################### ###########################
# # # #
@ -773,7 +777,6 @@ changeMetadata.keywords=Keywords:
changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss): changeMetadata.modDate=Modification Date (yyyy/MM/dd HH:mm:ss):
changeMetadata.producer=Producer: changeMetadata.producer=Producer:
changeMetadata.subject=Subject: changeMetadata.subject=Subject:
changeMetadata.title=Title:
changeMetadata.trapped=Trapped: changeMetadata.trapped=Trapped:
changeMetadata.selectText.4=Other Metadata: changeMetadata.selectText.4=Other Metadata:
changeMetadata.selectText.5=Add Custom Metadata Entry changeMetadata.selectText.5=Add Custom Metadata Entry
@ -823,3 +826,9 @@ PDFToXML.title=PDF to XML
PDFToXML.header=PDF to XML PDFToXML.header=PDF to XML
PDFToXML.credit=This service uses LibreOffice for file conversion. PDFToXML.credit=This service uses LibreOffice for file conversion.
PDFToXML.submit=Convert PDFToXML.submit=Convert
#PDFToCSV
PDFToCSV.title=PDF to CSV
PDFToCSV.header=PDF to CSV
PDFToCSV.credit=This service uses LibreOffice for file conversion.
PDFToCSV.submit=Convert

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M0 64C0 28.7 28.7 0 64 0H224V128c0 17.7 14.3 32 32 32H384V304H176c-35.3 0-64 28.7-64 64V512H64c-35.3 0-64-28.7-64-64V64zm384 64H256V0L384 128zM200 352h16c22.1 0 40 17.9 40 40v8c0 8.8-7.2 16-16 16s-16-7.2-16-16v-8c0-4.4-3.6-8-8-8H200c-4.4 0-8 3.6-8 8v80c0 4.4 3.6 8 8 8h16c4.4 0 8-3.6 8-8v-8c0-8.8 7.2-16 16-16s16 7.2 16 16v8c0 22.1-17.9 40-40 40H200c-22.1 0-40-17.9-40-40V392c0-22.1 17.9-40 40-40zm133.1 0H368c8.8 0 16 7.2 16 16s-7.2 16-16 16H333.1c-7.2 0-13.1 5.9-13.1 13.1c0 5.2 3 9.9 7.8 12l37.4 16.6c16.3 7.2 26.8 23.4 26.8 41.2c0 24.9-20.2 45.1-45.1 45.1H304c-8.8 0-16-7.2-16-16s7.2-16 16-16h42.9c7.2 0 13.1-5.9 13.1-13.1c0-5.2-3-9.9-7.8-12l-37.4-16.6c-16.3-7.2-26.8-23.4-26.8-41.2c0-24.9 20.2-45.1 45.1-45.1zm98.9 0c8.8 0 16 7.2 16 16v31.6c0 23 5.5 45.6 16 66c10.5-20.3 16-42.9 16-66V368c0-8.8 7.2-16 16-16s16 7.2 16 16v31.6c0 34.7-10.3 68.7-29.6 97.6l-5.1 7.7c-3 4.5-8 7.1-13.3 7.1s-10.3-2.7-13.3-7.1l-5.1-7.7c-19.3-28.9-29.6-62.9-29.6-97.6V368c0-8.8 7.2-16 16-16z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{PDFToXML.title})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{PDFToCSV.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/csv}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToCSV.submit}"></button>
</form>
<p class="mt-3" th:text="#{PDFToCSV.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View File

@ -1,13 +1,13 @@
<div th:fragment="navbar" class="mx-auto"> <div th:fragment="navbar" class="mx-auto">
<script src="js/languageSelection.js"></script> <script src="js/languageSelection.js"></script>
<script th:inline="javascript"> <script th:inline="javascript">
const currentVersion = /*[[${@appVersion}]]*/ ''; const currentVersion = /*[[${@appVersion}]]*/ '';
const noFavourites = /*[[#{noFavourites}]]*/ ''; const noFavourites = /*[[#{noFavourites}]]*/ '';
</script> </script>
<script th:src="@{js/githubVersion.js}"></script> <script th:src="@{js/githubVersion.js}"></script>
<link rel="stylesheet" href="css/navbar.css"> <link rel="stylesheet" href="css/navbar.css">
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container "> <div class="container ">
@ -39,7 +39,7 @@
</a> </a>
</li>--> </li>-->
<li class="nav-item nav-item-separator"></li> <li class="nav-item nav-item-separator"></li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' ? 'active' : ''"> <li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' ? 'active' : ''">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon"> <img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
@ -62,8 +62,8 @@
</div> </div>
</li> </li>
<li class="nav-item nav-item-separator"></li> <li class="nav-item nav-item-separator"></li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='pdf-to-pdfa' OR ${currentPage}=='file-to-pdf' OR ${currentPage}=='xlsx-to-pdf' OR ${currentPage}=='pdf-to-word' OR ${currentPage}=='pdf-to-presentation' OR ${currentPage}=='pdf-to-text' OR ${currentPage}=='pdf-to-html' OR ${currentPage}=='pdf-to-xml' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" <li class="nav-item dropdown" th:classappend="${currentPage}=='pdf-to-img' OR ${currentPage}=='img-to-pdf' OR ${currentPage}=='pdf-to-pdfa' OR ${currentPage}=='file-to-pdf' OR ${currentPage}=='xlsx-to-pdf' OR ${currentPage}=='pdf-to-word' OR ${currentPage}=='pdf-to-presentation' OR ${currentPage}=='pdf-to-text' OR ${currentPage}=='pdf-to-html' OR ${currentPage}=='pdf-to-xml' ? 'active' : ''"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false"> aria-haspopup="true" aria-expanded="false">
<img class="icon" src="images/arrow-left-right.svg" alt="icon" style="width: 16px; height: 16px; vertical-align: middle;"> <img class="icon" src="images/arrow-left-right.svg" alt="icon" style="width: 16px; height: 16px; vertical-align: middle;">
@ -91,7 +91,7 @@
</div> </div>
</li> </li>
<li class="nav-item nav-item-separator"></li> <li class="nav-item nav-item-separator"></li>
<li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='add-watermark' OR ${currentPage}=='cert-sign' OR ${currentPage}=='sanitize-pdf' ? 'active' : ''"> <li class="nav-item dropdown" th:classappend="${currentPage}=='add-password' OR ${currentPage}=='remove-password' OR ${currentPage}=='add-watermark' OR ${currentPage}=='cert-sign' OR ${currentPage}=='sanitize-pdf' ? 'active' : ''">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@ -105,6 +105,8 @@
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'images/award.svg', 'home.certSign.title', 'home.certSign.desc', 'certSign.tags')}"></div> <div th:replace="~{fragments/navbarEntry :: navbarEntry ('cert-sign', 'images/award.svg', 'home.certSign.title', 'home.certSign.desc', 'certSign.tags')}"></div>
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('sanitize-pdf', 'images/sanitize.svg', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags')}"></div> <div th:replace="~{fragments/navbarEntry :: navbarEntry ('sanitize-pdf', 'images/sanitize.svg', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags')}"></div>
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('auto-redact', 'images/eraser-fill.svg', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags')}"></div> <div th:replace="~{fragments/navbarEntry :: navbarEntry ('auto-redact', 'images/eraser-fill.svg', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags')}"></div>
<div th:replace="~{fragments/navbarEntry :: navbarEntry ('auto-extract', 'images/eraser-fill.svg', 'home.tableExtraxt.title', 'home.tableExtraxt.desc', 'tableExtraxt.tags')}"></div>
</div> </div>
</li> </li>
@ -179,7 +181,7 @@
</li> </li>
<!-- Search Button and Search Bar --> <!-- Search Button and Search Bar -->
<li class="nav-item position-relative"> <li class="nav-item position-relative">
<a href="#" class="nav-link" id="search-icon"> <a href="#" class="nav-link" id="search-icon">
<img class="navbar-icon" src="images/search.svg" alt="icon" width="24" height="24"> <img class="navbar-icon" src="images/search.svg" alt="icon" width="24" height="24">
</a> </a>
@ -191,45 +193,45 @@
<!-- Search Results --> <!-- Search Results -->
<div id="searchResults" class="border p-2 bg-white search-results"></div> <div id="searchResults" class="border p-2 bg-white search-results"></div>
</div> </div>
</li> </li>
<style> <style>
#search-icon i { #search-icon i {
font-size: 24px; /* Adjust this to your desired size */ font-size: 24px; /* Adjust this to your desired size */
transition: color 0.3s; transition: color 0.3s;
} }
#search-icon:hover i { #search-icon:hover i {
color: #666; /* Adjust this to your hover color */ color: #666; /* Adjust this to your hover color */
} }
#navbarSearch { #navbarSearch {
transition: all 0.3s; transition: all 0.3s;
max-height: 0; max-height: 0;
overflow: hidden; overflow: hidden;
} }
#navbarSearch.show { #navbarSearch.show {
max-height: 300px; /* Adjust this to your desired max height */ max-height: 300px; /* Adjust this to your desired max height */
} }
.search-input { .search-input {
transition: border 0.3s, box-shadow 0.3s; transition: border 0.3s, box-shadow 0.3s;
} }
.search-input:focus { .search-input:focus {
border-color: #666; /* Adjust this to your focus color */ border-color: #666; /* Adjust this to your focus color */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */
} }
#searchResults { #searchResults {
max-width: 300px; /* Adjust to your preferred width */ max-width: 300px; /* Adjust to your preferred width */
transition: height 0.3s ease; /* Smooth height transition */ transition: height 0.3s ease; /* Smooth height transition */
} }
/* Set a fixed height and styling for each search result item */ /* Set a fixed height and styling for each search result item */
.search-results a { .search-results a {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; /* space between icon and text */ gap: 10px; /* space between icon and text */
@ -237,9 +239,9 @@
overflow: hidden; /* Prevent content from overflowing */ overflow: hidden; /* Prevent content from overflowing */
white-space: nowrap; /* Prevent text from wrapping to next line */ white-space: nowrap; /* Prevent text from wrapping to next line */
text-overflow: ellipsis; /* Truncate text if it's too long */ text-overflow: ellipsis; /* Truncate text if it's too long */
} }
</style> </style>
</ul> </ul>
@ -301,11 +303,11 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script src="js/settings.js"></script> <script src="js/settings.js"></script>

View File

@ -8,7 +8,7 @@
<body> <body>
<div id="page-container"> <div id="page-container">
<div id="content-wrap"> <div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div> <div th:insert="~{fragments/navbar.html :: navbar}"></div>
<!-- Jumbotron --> <!-- Jumbotron -->
@ -93,13 +93,14 @@
<div th:replace="~{fragments/card :: card(id='show-javascript', cardTitle=#{home.showJS.title}, cardText=#{home.showJS.desc}, cardLink='show-javascript', svgPath='images/js.svg')}"></div> <div th:replace="~{fragments/card :: card(id='show-javascript', cardTitle=#{home.showJS.title}, cardText=#{home.showJS.desc}, cardLink='show-javascript', svgPath='images/js.svg')}"></div>
<div th:replace="~{fragments/card :: card(id='auto-redact', cardTitle=#{home.autoRedact.title}, cardText=#{home.autoRedact.desc}, cardLink='auto-redact', svgPath='images/eraser-fill.svg')}"></div> <div th:replace="~{fragments/card :: card(id='auto-redact', cardTitle=#{home.autoRedact.title}, cardText=#{home.autoRedact.desc}, cardLink='auto-redact', svgPath='images/eraser-fill.svg')}"></div>
<div th:replace="~{fragments/card :: card(id='pdf-to-csv', cardTitle=#{home.tableExtraxt.title}, cardText=#{home.tableExtraxt.desc}, cardLink='pdf-to-csv', svgPath='images/pdf-csv.svg')}"></div>
</div> </div>
</div> </div> </div> </div>
<div th:insert="~{fragments/footer.html :: footer}"></div> <div th:insert="~{fragments/footer.html :: footer}"></div>
</div> </div>
</body> </body>
</html> </html>