diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java
index 5b938c723a1c5ef1dd0cfa7a27181acf33a61437..732c833e85644fee9b7d44f3bd4c55c3bbb7e5ec 100644
--- a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java
+++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/TransactionImportController.java
@@ -2,22 +2,43 @@ package de.deadlocker8.budgetmaster.transactions;
 
 import de.deadlocker8.budgetmaster.controller.BaseController;
 import de.deadlocker8.budgetmaster.services.HelpersService;
+import de.deadlocker8.budgetmaster.transactions.csvImport.CsvRow;
 import de.deadlocker8.budgetmaster.utils.Mappings;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
 
 @Controller
 @RequestMapping(Mappings.TRANSACTION_IMPORT)
 public class TransactionImportController extends BaseController
 {
+	private static class ModelAttributes
+	{
+		public static final String ERROR_UPLOAD = "errorUpload";
+	}
+
 	private static class ReturnValues
 	{
 		public static final String TRANSACTION_IMPORT = "transactions/transactionImport";
+		public static final String REDIRECT_CANCEL = "redirect:/transactionImport/cancel";
+
+	}
+
+	private static class RequestAttributeNames
+	{
+		public static final String IMPORTED_FILE = "importedFile";
+		public static final String CSV_ROWS = "csvRows";
 	}
 
 	private final TransactionService transactionService;
@@ -35,4 +56,44 @@ public class TransactionImportController extends BaseController
 	{
 		return ReturnValues.TRANSACTION_IMPORT;
 	}
+
+	@PostMapping("/upload")
+	public String upload(WebRequest request, Model model, @RequestParam("file") MultipartFile file)
+	{
+		if(file.isEmpty())
+		{
+			return ReturnValues.REDIRECT_CANCEL;
+		}
+
+		try
+		{
+			final String csvString = new String(file.getBytes(), StandardCharsets.UTF_8);
+
+			String fileName = file.getOriginalFilename();
+			if(fileName == null)
+			{
+				fileName = file.getName();
+			}
+
+			request.setAttribute(RequestAttributeNames.IMPORTED_FILE, fileName, RequestAttributes.SCOPE_SESSION);
+			request.setAttribute(RequestAttributeNames.CSV_ROWS, List.of(new CsvRow("12.12.22", "sdfghjklö", "12.30")), RequestAttributes.SCOPE_SESSION);
+		}
+		catch(Exception e)
+		{
+			LOGGER.error("CSV upload failed", e);
+
+			model.addAttribute(ModelAttributes.ERROR_UPLOAD, e.getMessage());
+		}
+
+		return ReturnValues.TRANSACTION_IMPORT;
+	}
+
+	@GetMapping("/cancel")
+	public String cancel(WebRequest request)
+	{
+		request.removeAttribute(RequestAttributeNames.IMPORTED_FILE, RequestAttributes.SCOPE_SESSION);
+		request.removeAttribute(RequestAttributeNames.CSV_ROWS, RequestAttributes.SCOPE_SESSION);
+
+		return ReturnValues.TRANSACTION_IMPORT;
+	}
 }
\ No newline at end of file
diff --git a/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvImport/CsvRow.java b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvImport/CsvRow.java
new file mode 100644
index 0000000000000000000000000000000000000000..d09d23d0971ef207489e322aa7a7438f9bef900c
--- /dev/null
+++ b/BudgetMasterServer/src/main/java/de/deadlocker8/budgetmaster/transactions/csvImport/CsvRow.java
@@ -0,0 +1,33 @@
+package de.deadlocker8.budgetmaster.transactions.csvImport;
+
+import java.util.List;
+
+public class CsvRow
+{
+	private final List<String> columns;
+
+	public CsvRow(List<String> columns)
+	{
+		this.columns = columns;
+	}
+
+	public CsvRow(String... columns)
+	{
+		this.columns = List.of(columns);
+	}
+
+	public List<String> getColumns()
+	{
+		return columns;
+	}
+
+	@Override
+	public String toString()
+	{
+		return "CsvRow{" +
+				"columns=" + columns +
+				'}';
+	}
+}
+
+
diff --git a/BudgetMasterServer/src/main/resources/languages/base_de.properties b/BudgetMasterServer/src/main/resources/languages/base_de.properties
index 0840702580d5b6c19ab1d6f2598ad2c6676d4751..344f4bef3819de11fc78f81ff96a2f280f96ee50 100644
--- a/BudgetMasterServer/src/main/resources/languages/base_de.properties
+++ b/BudgetMasterServer/src/main/resources/languages/base_de.properties
@@ -368,6 +368,8 @@ transaction.new.label.repeating=Wiederholung
 transaction.new.label.repeating.all=Alle
 transactions.recurring.headline=Aktive wiederholende Buchungen
 transactions.recurring.placeholder=Keine aktiven wiederholenden Buchungen
+transactions.import.overview=Übersicht
+transactions.import.column=Spalte
 
 repeating.button.add=Wiederholung hinzufügen
 repeating.button.remove=Wiederholung entfernen
diff --git a/BudgetMasterServer/src/main/resources/languages/base_en.properties b/BudgetMasterServer/src/main/resources/languages/base_en.properties
index be2bde2432fc2c1a8d79cac9f8a23f4fafb07c12..d0c244cf978f5270f9bbe9d1c871f8c5f2ebbcd0 100644
--- a/BudgetMasterServer/src/main/resources/languages/base_en.properties
+++ b/BudgetMasterServer/src/main/resources/languages/base_en.properties
@@ -368,6 +368,8 @@ transaction.new.label.repeating=Repeating
 transaction.new.label.repeating.all=Every
 transactions.recurring.headline=Active Recurring Transactions
 transactions.recurring.placeholder=No active recurring transactions
+transactions.import.overview=Overview
+transactions.import.column=Column
 
 repeating.button.add=Add repetition
 repeating.button.remove=Remove repetition
diff --git a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl
index ac7adb4e04baa0798fb0dc2280f75e3c415dec09..41cac76727a76a641aee055c5c2ec40b3978ae22 100644
--- a/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl
+++ b/BudgetMasterServer/src/main/resources/templates/transactions/transactionImport.ftl
@@ -20,6 +20,27 @@
                 </div>
 
                 <@header.content>
+                    <div class="container">
+                        <#if importedFile??>
+                            <div class="row center-align">
+                                <div class="col s12 m12 l8 offset-l2 headline-small text-green">
+                                    <i class="fas fa-file-csv"></i> ${importedFile}
+                                </div>
+                            </div>
+
+                            <div class="row center-align">
+                                <div class="col s12">
+                                    <@header.buttonLink url='/transactionImport/cancel' icon='clear' localizationKey='cancel' color='red' classes='text-white'/>
+                                </div>
+                            </div>
+                        <#else>
+                            <@csvUpload/>
+                        </#if>
+                    </div>
+
+                    <#if csvRows??>
+                        <@renderCsvRows/>
+                    </#if>
                 </@header.content>
             </div>
         </main>
@@ -28,4 +49,54 @@
         <#import "../helpers/scripts.ftl" as scripts>
         <@scripts.scripts/>
     </@header.body>
-</html>
\ No newline at end of file
+</html>
+
+<#macro csvUpload>
+    <form id="form-csv-import" method="POST" action="<@s.url '/transactionImport/upload'/>" enctype="multipart/form-data" accept-charset="UTF-8">
+        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
+
+        <div class="row">
+            <div class="col s12 m12 l8 offset-l2 file-field input-field">
+                <div class="btn background-blue">
+                    <i class="fas fa-file-csv"></i>
+                    <input id="inputCsvImport" type="file" accept=".csv" name="file">
+                </div>
+                <div class="file-path-wrapper">
+                    <input class="file-path validate" type="text">
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <div class="col s12 center-align">
+                <@header.buttonSubmit name='action' icon='cloud_upload' localizationKey='settings.database.import' id='button-confirm-csv-import' classes='text-white'/>
+            </div>
+        </div>
+    </form>
+</#macro>
+
+<#macro renderCsvRows>
+    <div class="container">
+        <div class="section center-align">
+            <div class="headline-small">${locale.getString("transactions.import.overview")}</div>
+        </div>
+    </div>
+
+    <div class="container">
+        <table class="bordered centered">
+            <tr>
+                <#list 1..csvRows[0].getColumns()?size as i>
+                    <td class="bold">${locale.getString("transactions.import.column")} ${i?c}</td>
+                </#list>
+            </tr>
+
+            <#list csvRows as cswRow>
+                <tr>
+                    <#list cswRow.getColumns() as csvColumn>
+                        <td>${csvColumn}</td>
+                    </#list>
+                </tr>
+            </#list>
+        </table>
+    </div>
+</#macro>
\ No newline at end of file