Fix: correct download filename in 2.15.0 (#9599)

---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
This commit is contained in:
shamoon 2025-04-09 09:03:38 -07:00 committed by GitHub
parent b9f7428f2f
commit 43b2527275
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 41 deletions

View File

@ -1,5 +1,5 @@
import { AsyncPipe, NgTemplateOutlet } from '@angular/common' import { AsyncPipe, NgTemplateOutlet } from '@angular/common'
import { HttpClient } from '@angular/common/http' import { HttpClient, HttpResponse } from '@angular/common/http'
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
import { import {
FormArray, FormArray,
@ -995,44 +995,48 @@ export class DocumentDetailComponent
this.documentId, this.documentId,
original original
) )
this.http.get(downloadUrl, { responseType: 'blob' }).subscribe({ this.http
next: (blob) => { .get(downloadUrl, { observe: 'response', responseType: 'blob' })
this.downloading = false .subscribe({
const blobParts = [blob] next: (response: HttpResponse<Blob>) => {
const file = new File( const filename = response.headers
blobParts, .get('Content-Disposition')
original ?.split(';')
? this.document.original_file_name ?.find((part) => part.trim().startsWith('filename='))
: this.document.archived_file_name, ?.split('=')[1]
{ ?.replace(/['"]/g, '')
type: original ? this.document.mime_type : 'application/pdf', const blob = new Blob([response.body], {
} type: response.body.type,
)
if (
!this.deviceDetectorService.isDesktop() &&
navigator.canShare &&
navigator.canShare({ files: [file] })
) {
navigator.share({
files: [file],
}) })
} else { this.downloading = false
const url = URL.createObjectURL(blob) const file = new File([blob], filename, {
const a = document.createElement('a') type: response.body.type,
a.href = url })
a.download = this.document.title if (
a.click() !this.deviceDetectorService.isDesktop() &&
URL.revokeObjectURL(url) navigator.canShare &&
} navigator.canShare({ files: [file] })
}, ) {
error: (error) => { navigator.share({
this.downloading = false files: [file],
this.toastService.showError( })
$localize`Error downloading document`, } else {
error const url = URL.createObjectURL(blob)
) const a = document.createElement('a')
}, a.href = url
}) a.download = filename
a.click()
URL.revokeObjectURL(url)
}
},
error: (error) => {
this.downloading = false
this.toastService.showError(
$localize`Error downloading document`,
error
)
},
})
} }
hasNext() { hasNext() {

View File

@ -2376,9 +2376,13 @@ def serve_file(*, doc: Document, use_archive: bool, disposition: str):
# RFC 5987 addresses this issue # RFC 5987 addresses this issue
# see https://datatracker.ietf.org/doc/html/rfc5987#section-4.2 # see https://datatracker.ietf.org/doc/html/rfc5987#section-4.2
# Chromium cannot handle commas in the filename # Chromium cannot handle commas in the filename
filename_normalized = normalize("NFKD", filename.replace(",", "_")).encode( filename_normalized = (
"ascii", normalize("NFKD", filename.replace(",", "_"))
"ignore", .encode(
"ascii",
"ignore",
)
.decode("ascii")
) )
filename_encoded = quote(filename) filename_encoded = quote(filename)
content_disposition = ( content_disposition = (

View File

@ -565,6 +565,10 @@ if DEBUG:
# Allow access from the angular development server during debugging # Allow access from the angular development server during debugging
CORS_ALLOWED_ORIGINS.append("http://localhost:4200") CORS_ALLOWED_ORIGINS.append("http://localhost:4200")
CORS_EXPOSE_HEADERS = [
"Content-Disposition",
]
ALLOWED_HOSTS = __get_list("PAPERLESS_ALLOWED_HOSTS", ["*"]) ALLOWED_HOSTS = __get_list("PAPERLESS_ALLOWED_HOSTS", ["*"])
if ALLOWED_HOSTS != ["*"]: if ALLOWED_HOSTS != ["*"]:
# always allow localhost. Necessary e.g. for healthcheck in docker. # always allow localhost. Necessary e.g. for healthcheck in docker.