Files
itc.pidi-3-docs/chapters/execution/downloads.tex
T

40 lines
4.4 KiB
TeX

\section{Downloads}
\label{sec:downloads}
\subsection{Einzeldownload über zeitlich begrenzte Zugriffs-URLs}
Für den Download einzelner Dokumente wäre es möglich gewesen, den Inhalt aus dem Speicher zu lesen und durch die Anwendung hindurch an den Browser weiterzureichen. Stattdessen wird eine zeitlich begrenzte Zugriffs-URL erzeugt, mit der der Browser das Dokument unmittelbar vom Speicher abruft \autocite{aws-presigned-urls}.
Der Vorteil liegt darin, dass die eigentliche Datenübertragung nicht über die Anwendung läuft. Ein großes Dokument belegt weder Arbeitsspeicher noch eine Verbindung des Webservers; die Anwendung ist nach dem Erzeugen der URL nicht mehr beteiligt. Die URL ist nur wenige Minuten gültig und danach wertlos.
Wichtig ist dabei, dass die Berechtigungsprüfung \emph{vor} dem Erzeugen der URL stattfindet. Die URL selbst trägt keine Prüfung mehr in sich — wer sie besitzt, kann innerhalb ihrer Gültigkeitsdauer auf das Dokument zugreifen. Sie darf deshalb nur für einen Schlüssel erzeugt werden, der nachweislich innerhalb des Kundenordners liegt.
Genau an dieser Stelle setzte der überwiegende Teil des Reviews an. Die Prüfung, dass ein angeforderter Pfad den Kundenordner nicht verlässt, war die inhaltlich kritischste Einzelanforderung des Moduls, und die wiederholten Rückfragen dazu führten zu der in Abschnitt~\ref{sec:architecture} beschriebenen Einführung eigener Pfadtypen. Der Pull Request durchlief 23 Iterationen; ein erheblicher Anteil davon entfiel auf dieses Refactoring und nicht auf die Downloadfunktion selbst.
Zusätzlich musste sichergestellt werden, dass das Dokument unter seinem ursprünglichen Namen ankommt. Da der Schlüssel im Speicher den vollständigen Pfad enthält, würde ein unbehandelter Download unter einem technischen Namen gespeichert. Der gewünschte Dateiname wird deshalb ausdrücklich mitgegeben.
\subsection{ZIP-Download}
Für den Download mehrerer Dokumente erhält jede Zeile eine Auswahlbox. Die Schaltfläche für den ZIP-Download ist deaktiviert, solange nichts ausgewählt ist, und wird erst mit der ersten Auswahl freigegeben. Damit ist die Anforderung, dass ohne Auswahl kein Download ausgelöst werden kann, unmittelbar in der Bedienoberfläche abgebildet und muss nicht durch eine Fehlermeldung nachgereicht werden.
Abbildung~\ref{fig:zip-stream} zeigt den Ablauf.
\begin{figure}[H]
\centering
\includegraphics[width=0.95\textwidth]{figures/diagrams/zip-stream.pdf}
\caption{Ablauf des ZIP-Downloads}
\label{fig:zip-stream}
\end{figure}
Das Archiv wird erst beim Klick erzeugt und nicht im Voraus vorgehalten — auch dies eine ausdrückliche Anforderung. Entscheidend für die Umsetzung ist, dass es dabei zu keinem Zeitpunkt vollständig im Arbeitsspeicher oder auf der Festplatte entsteht: Die Anwendung öffnet die Antwort als Archivstrom, liest die ausgewählten Dokumente nacheinander aus dem Speicher und schreibt sie unmittelbar als Einträge hinein \autocite{dotnet-zip}. Die komprimierten Daten fließen dabei direkt zum Browser.
Diese Arbeitsweise ist notwendig, weil die Gesamtgröße einer Auswahl nicht begrenzt ist. Würde das Archiv zunächst vollständig aufgebaut, bestimmte die größte denkbare Auswahl den Speicherbedarf des Servers. Beim Strömen bleibt dieser dagegen unabhängig von der Auswahlgröße konstant. Die Struktur innerhalb des Archivs entspricht der Ablagestruktur, sodass die Typordner erhalten bleiben.
\subsection{ZIP auch bei einer einzelnen Datei}
Im Review stellte \emph{Sarah Hinzmann} die Frage, ob auch bei nur einer ausgewählten Datei ein Archiv erzeugt werden solle, statt die Datei direkt auszuliefern.
Die Entscheidung fiel für das Archiv. Der Grund ist die Vorhersagbarkeit der Bedienung: Die Schaltfläche ist mit „Als ZIP herunterladen" beschriftet, und wer sie betätigt, soll ein Archiv erhalten — unabhängig davon, wie viele Dokumente ausgewählt sind. Wer eine einzelne Datei unverpackt benötigt, verwendet die Download-Schaltfläche in der jeweiligen Zeile. Eine automatische Umschaltung des Verhaltens abhängig von der Auswahlgröße wäre für den Benutzer schwerer zu antizipieren und hätte zudem bedeutet, dass ein Skript auf der Seite die beiden Fälle unterscheiden müsste.
Der Fall zeigt beispielhaft, wie eine scheinbar kleine Bedienfrage eine begründete Entscheidung erfordert. Beide Varianten sind vertretbar; ausschlaggebend war, dass jede Schaltfläche genau eine Bedeutung behält.