From d3b09321fc2ac1ddaf0534d683351746d56d643b Mon Sep 17 00:00:00 2001 From: entholzer Date: Thu, 28 Nov 2024 22:15:26 +0100 Subject: [PATCH] fix file downloads --- .../aet/artemis/core/web/FileResource.java | 22 ++++++++-------- .../lecture-attachments.component.html | 2 +- .../lecture/lecture-attachments.component.ts | 4 +-- .../attachment-unit.component.ts | 2 +- .../course-lecture-details.component.html | 2 +- .../course-lecture-details.component.ts | 6 ++--- .../webapp/app/shared/http/file.service.ts | 25 +++++++++++++------ 7 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/main/java/de/tum/cit/aet/artemis/core/web/FileResource.java b/src/main/java/de/tum/cit/aet/artemis/core/web/FileResource.java index 27332e5343a7..11c5d1278609 100644 --- a/src/main/java/de/tum/cit/aet/artemis/core/web/FileResource.java +++ b/src/main/java/de/tum/cit/aet/artemis/core/web/FileResource.java @@ -1,6 +1,8 @@ package de.tum.cit.aet.artemis.core.web; import static de.tum.cit.aet.artemis.core.config.Constants.PROFILE_CORE; +import static org.apache.velocity.shaded.commons.io.FilenameUtils.getBaseName; +import static org.apache.velocity.shaded.commons.io.FilenameUtils.getExtension; import java.io.IOException; import java.net.FileNameMap; @@ -409,20 +411,18 @@ public ResponseEntity getExamUserImage(@PathVariable Long examUserId) { /** * GET /files/attachments/lecture/:lectureId/:filename : Get the lecture attachment * - * @param lectureId ID of the lecture, the attachment belongs to - * @param filename the filename of the file + * @param lectureId ID of the lecture, the attachment belongs to + * @param attachmentName the filename of the file * @return The requested file, 403 if the logged-in user is not allowed to access it, or 404 if the file doesn't exist */ - @GetMapping("files/attachments/lecture/{lectureId}/{filename}") + @GetMapping("files/attachments/lecture/{lectureId}/{attachmentName}") @EnforceAtLeastStudent - public ResponseEntity getLectureAttachment(@PathVariable Long lectureId, @PathVariable String filename) { - log.debug("REST request to get lecture attachment : {}", filename); - String fileNameWithoutSpaces = filename.replaceAll(" ", "_"); - sanitizeFilenameElseThrow(fileNameWithoutSpaces); + public ResponseEntity getLectureAttachment(@PathVariable Long lectureId, @PathVariable String attachmentName) { + log.debug("REST request to get lecture attachment : {}", attachmentName); List lectureAttachments = attachmentRepository.findAllByLectureId(lectureId); - Attachment attachment = lectureAttachments.stream().filter(lectureAttachment -> lectureAttachment.getLink().endsWith(fileNameWithoutSpaces)).findAny() - .orElseThrow(() -> new EntityNotFoundException("Attachment", filename)); + Attachment attachment = lectureAttachments.stream().filter(lectureAttachment -> lectureAttachment.getName().equals(getBaseName(attachmentName))).findAny() + .orElseThrow(() -> new EntityNotFoundException("Attachment", attachmentName)); // get the course for a lecture attachment Lecture lecture = attachment.getLecture(); @@ -431,7 +431,7 @@ public ResponseEntity getLectureAttachment(@PathVariable Long lectureId, // check if the user is authorized to access the requested attachment unit checkAttachmentAuthorizationOrThrow(course, attachment); - return buildFileResponse(getActualPathFromPublicPathString(attachment.getLink()), Optional.of(attachment.getName())); + return buildFileResponse(getActualPathFromPublicPathString(attachment.getLink()), Optional.of(attachmentName)); } /** @@ -487,7 +487,7 @@ public ResponseEntity getAttachmentUnitAttachment(@PathVariable Long att // check if the user is authorized to access the requested attachment unit checkAttachmentAuthorizationOrThrow(course, attachment); - return buildFileResponse(getActualPathFromPublicPathString(attachment.getLink()), Optional.of(attachment.getName())); + return buildFileResponse(getActualPathFromPublicPathString(attachment.getLink()), Optional.of(attachment.getName() + "." + getExtension(attachment.getLink()))); } /** diff --git a/src/main/webapp/app/lecture/lecture-attachments.component.html b/src/main/webapp/app/lecture/lecture-attachments.component.html index 6192f270d64e..6ed7e3ed3ea8 100644 --- a/src/main/webapp/app/lecture/lecture-attachments.component.html +++ b/src/main/webapp/app/lecture/lecture-attachments.component.html @@ -61,7 +61,7 @@

{{ attachment.attachmentType }} @if (!isDownloadingAttachmentLink) { - + {{ attachment.name }} } diff --git a/src/main/webapp/app/lecture/lecture-attachments.component.ts b/src/main/webapp/app/lecture/lecture-attachments.component.ts index 262bbfe593a5..ece1cd67473b 100644 --- a/src/main/webapp/app/lecture/lecture-attachments.component.ts +++ b/src/main/webapp/app/lecture/lecture-attachments.component.ts @@ -200,10 +200,10 @@ export class LectureAttachmentsComponent implements OnDestroy { return item.id; } - downloadAttachment(downloadUrl: string): void { + downloadAttachment(downloadName: string, downloadUrl: string): void { if (!this.isDownloadingAttachmentLink) { this.isDownloadingAttachmentLink = downloadUrl; - this.fileService.downloadFile(this.fileService.replaceLectureAttachmentPrefixAndUnderscores(downloadUrl)); + this.fileService.downloadFileByAttachmentName(downloadUrl, downloadName); this.isDownloadingAttachmentLink = undefined; } } diff --git a/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts b/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts index 5634aeda7a5e..4d70111dc9c9 100644 --- a/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts +++ b/src/main/webapp/app/overview/course-lectures/attachment-unit/attachment-unit.component.ts @@ -51,7 +51,7 @@ export class AttachmentUnitComponent extends LectureUnitDirective
  • @if (!isDownloadingLink) { - + {{ attachment.name }} } diff --git a/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts b/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts index 28f73df62dc5..45a2525a5554 100644 --- a/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts +++ b/src/main/webapp/app/overview/course-lectures/course-lecture-details.component.ts @@ -128,10 +128,10 @@ export class CourseLectureDetailsComponent extends AbstractScienceComponent impl return attachment.link.split('.').pop()!; } - downloadAttachment(downloadUrl?: string): void { - if (!this.isDownloadingLink && downloadUrl) { + downloadAttachment(downloadUrl?: string, donwloadName?: string): void { + if (!this.isDownloadingLink && downloadUrl && donwloadName) { this.isDownloadingLink = downloadUrl; - this.fileService.downloadFile(this.fileService.replaceLectureAttachmentPrefixAndUnderscores(downloadUrl)); + this.fileService.downloadFileByAttachmentName(downloadUrl, donwloadName); this.isDownloadingLink = undefined; } } diff --git a/src/main/webapp/app/shared/http/file.service.ts b/src/main/webapp/app/shared/http/file.service.ts index 05960940f7aa..1c9f264f41d3 100644 --- a/src/main/webapp/app/shared/http/file.service.ts +++ b/src/main/webapp/app/shared/http/file.service.ts @@ -82,6 +82,23 @@ export class FileService { return newWindow; } + /** + * Downloads the file from the provided downloadUrl and the attachment name + * + * @param downloadUrl url that is stored in the attachment model + * @param downloadName the name given to the attachment + */ + downloadFileByAttachmentName(downloadUrl: string, downloadName: string) { + const downloadUrlComponents = downloadUrl.split('/'); + // take the last element + const extension = downloadUrlComponents.pop()!.split('.').pop(); + const restOfUrl = downloadUrlComponents.join('/'); + const normalizedDownloadUrl = restOfUrl + '/' + encodeURIComponent(downloadName + '.' + extension); + const newWindow = window.open('about:blank'); + newWindow!.location.href = normalizedDownloadUrl; + return newWindow; + } + /** * Downloads the merged PDF file. * @@ -124,12 +141,4 @@ export class FileService { replaceAttachmentPrefixAndUnderscores(link: string): string { return link.replace(/AttachmentUnit_\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}_/, '').replace(/_/g, ' '); } - - /** - * Removes the prefix from the file name, and replaces underscore with spaces - * @param link - */ - replaceLectureAttachmentPrefixAndUnderscores(link: string): string { - return link.replace(/LectureAttachment_\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}_/, '').replace(/_/g, ' '); - } }