mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	attach extension to download file if note present
This commit is contained in:
		| @@ -1,6 +1,5 @@ | |||||||
| "use strict"; | "use strict"; | ||||||
|  |  | ||||||
| const noteService = require('../../services/notes'); |  | ||||||
| const protectedSessionService = require('../../services/protected_session'); | const protectedSessionService = require('../../services/protected_session'); | ||||||
| const repository = require('../../services/repository'); | const repository = require('../../services/repository'); | ||||||
| const utils = require('../../services/utils'); | const utils = require('../../services/utils'); | ||||||
| @@ -45,7 +44,9 @@ async function downloadNoteFile(noteId, res, contentDisposition = true) { | |||||||
|     if (contentDisposition) { |     if (contentDisposition) { | ||||||
|         // (one) reason we're not using the originFileName (available as label) is that it's not |         // (one) reason we're not using the originFileName (available as label) is that it's not | ||||||
|         // available for older note revisions and thus would be inconsistent |         // available for older note revisions and thus would be inconsistent | ||||||
|         res.setHeader('Content-Disposition', utils.getContentDisposition(note.title || "untitled")); |         const filename = utils.formatDownloadTitle(note.title, note.type, note.mime); | ||||||
|  |  | ||||||
|  |         res.setHeader('Content-Disposition', utils.getContentDisposition(filename)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     res.setHeader('Content-Type', note.mime); |     res.setHeader('Content-Type', note.mime); | ||||||
|   | |||||||
| @@ -38,13 +38,7 @@ async function getNoteRevision(req) { | |||||||
|  * @return {string} |  * @return {string} | ||||||
|  */ |  */ | ||||||
| function getRevisionFilename(noteRevision) { | function getRevisionFilename(noteRevision) { | ||||||
|     let filename = noteRevision.title || "untitled"; |     let filename = utils.formatDownloadTitle(noteRevision.title, noteRevision.type, noteRevision.mime); | ||||||
|  |  | ||||||
|     if (noteRevision.type === 'text') { |  | ||||||
|         filename += '.html'; |  | ||||||
|     } else if (['relation-map', 'search'].includes(noteRevision.type)) { |  | ||||||
|         filename += '.json'; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const extension = path.extname(filename); |     const extension = path.extname(filename); | ||||||
|     const date = noteRevision.dateCreated |     const date = noteRevision.dateCreated | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ const Attribute = require('../entities/attribute'); | |||||||
| const hoistedNoteService = require('../services/hoisted_note'); | const hoistedNoteService = require('../services/hoisted_note'); | ||||||
| const protectedSessionService = require('../services/protected_session'); | const protectedSessionService = require('../services/protected_session'); | ||||||
| const log = require('../services/log'); | const log = require('../services/log'); | ||||||
|  | const utils = require('../services/utils'); | ||||||
| const noteRevisionService = require('../services/note_revisions'); | const noteRevisionService = require('../services/note_revisions'); | ||||||
| const attributeService = require('../services/attributes'); | const attributeService = require('../services/attributes'); | ||||||
| const request = require('./request'); | const request = require('./request'); | ||||||
| @@ -276,9 +277,9 @@ async function downloadImage(noteId, imageUrl) { | |||||||
| const downloadImagePromises = {}; | const downloadImagePromises = {}; | ||||||
|  |  | ||||||
| function replaceUrl(content, url, imageNote) { | function replaceUrl(content, url, imageNote) { | ||||||
|     const quoted = url.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); |     const quotedUrl = utils.quoteRegex(url); | ||||||
|  |  | ||||||
|     return content.replace(new RegExp(`\\s+src=[\"']${quoted}[\"']`, "g"), ` src="api/images/${imageNote.noteId}/${imageNote.title}"`); |     return content.replace(new RegExp(`\\s+src=[\"']${quotedUrl}[\"']`, "g"), ` src="api/images/${imageNote.noteId}/${imageNote.title}"`); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function downloadImages(noteId, content) { | async function downloadImages(noteId, content) { | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ const randtoken = require('rand-token').generator({source: 'crypto'}); | |||||||
| const unescape = require('unescape'); | const unescape = require('unescape'); | ||||||
| const escape = require('escape-html'); | const escape = require('escape-html'); | ||||||
| const sanitize = require("sanitize-filename"); | const sanitize = require("sanitize-filename"); | ||||||
|  | const mimeTypes = require('mime-types'); | ||||||
|  |  | ||||||
| function newEntityId() { | function newEntityId() { | ||||||
|     return randomString(12); |     return randomString(12); | ||||||
| @@ -166,10 +167,46 @@ function isStringNote(type, mime) { | |||||||
|         || STRING_MIME_TYPES.includes(mime); |         || STRING_MIME_TYPES.includes(mime); | ||||||
| } | } | ||||||
|  |  | ||||||
| function replaceAll(string, replaceWhat, replaceWith) { | function quoteRegex(url) { | ||||||
|     const escapedWhat = replaceWhat.replace(/([\/,!\\^${}\[\]().*+?|<>\-&])/g, "\\$&"); |     return url.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); | ||||||
|  | } | ||||||
|  |  | ||||||
|     return string.replace(new RegExp(escapedWhat, "g"), replaceWith); | function replaceAll(string, replaceWhat, replaceWith) { | ||||||
|  |     const quotedReplaceWhat = quoteRegex(replaceWhat); | ||||||
|  |  | ||||||
|  |     return string.replace(new RegExp(quotedReplaceWhat, "g"), replaceWith); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function formatDownloadTitle(filename, type, mime) { | ||||||
|  |     if (!filename) { | ||||||
|  |         filename = "untitled"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (type === 'text') { | ||||||
|  |         return filename + '.html'; | ||||||
|  |     } else if (['relation-map', 'search'].includes(type)) { | ||||||
|  |         return filename + '.json'; | ||||||
|  |     } else { | ||||||
|  |         if (!mime) { | ||||||
|  |             return filename; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         mime = mime.toLowerCase(); | ||||||
|  |         const filenameLc = filename.toLowerCase(); | ||||||
|  |         const extensions = mimeTypes.extensions[mime]; | ||||||
|  |  | ||||||
|  |         if (!extensions || extensions.length === 0) { | ||||||
|  |             return filename; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for (const ext of extensions) { | ||||||
|  |             if (filenameLc.endsWith('.' + ext)) { | ||||||
|  |                 return filename; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return filename + '.' + extensions[0]; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
| @@ -198,5 +235,7 @@ module.exports = { | |||||||
|     sanitizeFilenameForHeader, |     sanitizeFilenameForHeader, | ||||||
|     getContentDisposition, |     getContentDisposition, | ||||||
|     isStringNote, |     isStringNote, | ||||||
|     replaceAll |     quoteRegex, | ||||||
|  |     replaceAll, | ||||||
|  |     formatDownloadTitle | ||||||
| }; | }; | ||||||
		Reference in New Issue
	
	Block a user