🐛 Fix URL encoded filename on download (#675)
* fix: #665 url encoded filename on download * ♻️ back: refactor content-disposition attachment filename encoding (#665) --------- Co-authored-by: Eric Doughty-Papassideris <edoughtypapassideris@linagora.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
import { DriveFileDTO } from "../dto/drive-file-dto";
|
||||
import { DriveFileDTOBuilder } from "../../services/drive-file-dto-builder";
|
||||
import config from "config";
|
||||
import { formatAttachmentContentDispositionHeader } from "../../../files/utils";
|
||||
|
||||
export class DocumentsController {
|
||||
private driveFileDTOBuilder = new DriveFileDTOBuilder();
|
||||
@@ -510,9 +511,9 @@ export class DocumentsController {
|
||||
return response;
|
||||
} else if (archiveOrFile.file) {
|
||||
const data = archiveOrFile.file;
|
||||
const filename = encodeURIComponent(data.name.replace(/[^\p{L}0-9 _.-]/gu, ""));
|
||||
|
||||
response.header("Content-disposition", `attachment; filename="${filename}"`);
|
||||
response.header("Content-Disposition", formatAttachmentContentDispositionHeader(data.name));
|
||||
|
||||
if (data.size) response.header("Content-Length", data.size);
|
||||
response.type(data.mime);
|
||||
return response.send(data.file);
|
||||
@@ -565,7 +566,10 @@ export class DocumentsController {
|
||||
|
||||
try {
|
||||
const archive = await globalResolver.services.documents.documents.createZip(ids, context);
|
||||
reply.raw.setHeader("content-disposition", 'attachment; filename="twake_drive.zip"');
|
||||
reply.raw.setHeader(
|
||||
"content-disposition",
|
||||
formatAttachmentContentDispositionHeader("twake_drive.zip"),
|
||||
);
|
||||
|
||||
archive.on("finish", () => {
|
||||
reply.status(200);
|
||||
|
||||
@@ -22,3 +22,12 @@ export const fileIsMedia = (file: Partial<File>): boolean => {
|
||||
file.metadata?.mime?.startsWith("image/")
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate RFC 5987 UTF-8 encoding compliant header value for `Content-Disposition`
|
||||
* to make a browser download a reponse to a file with the provided name
|
||||
*/
|
||||
export const formatAttachmentContentDispositionHeader = (filename: string) => {
|
||||
const encoded = encodeURIComponent(filename.replace(/[^\p{L}0-9 _.-]/gu, ""));
|
||||
return `attachment; filename="${encoded}"; filename*=UTF-8''${encoded}`;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import { CompanyExecutionContext } from "../types";
|
||||
import { UploadOptions } from "../../types";
|
||||
import { PublicFile } from "../../entities/file";
|
||||
import gr from "../../../global-resolver";
|
||||
import { formatAttachmentContentDispositionHeader } from "../../utils";
|
||||
|
||||
export class FileController {
|
||||
async save(
|
||||
@@ -47,9 +48,8 @@ export class FileController {
|
||||
const params = request.params;
|
||||
try {
|
||||
const data = await gr.services.files.download(params.id, context);
|
||||
const filename = data.name.replace(/[^a-zA-Z0-9 -_.]/g, "");
|
||||
response.header("Content-Disposition", formatAttachmentContentDispositionHeader(data.name));
|
||||
|
||||
response.header("Content-disposition", `attachment; filename="${filename}"`);
|
||||
if (data.size) response.header("Content-Length", data.size);
|
||||
response.type(data.mime);
|
||||
return response.send(data.file);
|
||||
|
||||
Reference in New Issue
Block a user