Fix PostIt attachment links to match uploaded filenames
Apply the shared filename filter before URL encoding, preserve escaped URLs and original link labels, and add regression coverage for accented and spaced filenames. Update the changelog. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
96ff4af440
commit
63b44b5a92
3 changed files with 22 additions and 9 deletions
|
|
@ -24,6 +24,10 @@
|
|||
|
||||
### Fixed
|
||||
|
||||
* [PostIt] Les liens Markdown des pièces jointes utilisent désormais
|
||||
le même filtre de nom que l'upload serveur, avant l'encodage URL.
|
||||
Le libellé conserve le nom original, notamment ses accents.
|
||||
|
||||
* [Yavsc.Abstract][Yavsc.Blogs] Encodage des caractères non supportés
|
||||
dans les noms de fichiers téléversés avec `_` au lieu de `#`, pour
|
||||
éviter les fragments d'URL et permettre le téléchargement via les
|
||||
|
|
|
|||
|
|
@ -20,8 +20,13 @@ namespace PostIt.Tests;
|
|||
/// </summary>
|
||||
public class BlogAttachmentLinkTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Save_with_attachment_appends_absolute_link_derived_from_the_oidc_authority()
|
||||
[Theory]
|
||||
[InlineData("note.txt", "note.txt")]
|
||||
[InlineData("INSC_E03686381_SCHNEIDER_000113378AA__Troisi\u00e8me__.PDF",
|
||||
"INSC_E03686381_SCHNEIDER_000113378AA__Troisi_232me__.PDF")]
|
||||
[InlineData("rapport final.pdf", "rapport%20final.pdf")]
|
||||
public async Task Save_with_attachment_appends_absolute_link_derived_from_the_oidc_authority(
|
||||
string originalName, string urlName)
|
||||
{
|
||||
const string authority = "https://idp.example.test";
|
||||
|
||||
|
|
@ -53,7 +58,7 @@ public class BlogAttachmentLinkTests
|
|||
vm.DraftTitle = "Après";
|
||||
vm.DraftArticle = "Contenu modifié.";
|
||||
vm.DraftAttachments.Add(new BlogUploadFile(
|
||||
"note.txt",
|
||||
originalName,
|
||||
System.Text.Encoding.UTF8.GetBytes("payload test"),
|
||||
"text/plain"));
|
||||
|
||||
|
|
@ -68,12 +73,14 @@ public class BlogAttachmentLinkTests
|
|||
var sent = Assert.IsType<System.Func<HttpContent>>(linkPut.body);
|
||||
var multipartContent = Assert.IsType<MultipartFormDataContent>(sent());
|
||||
|
||||
var expectedUrl = $"{authority}/files/tester/blogs/42/note.txt";
|
||||
var sentStringContent = multipartContent.First() as StringContent ;
|
||||
var expectedUrl = $"{authority}/files/tester/blogs/42/{urlName}";
|
||||
var sentStringContent = Assert.IsType<StringContent>(multipartContent.First());
|
||||
|
||||
var sentString = await sentStringContent.ReadAsStringAsync(TestContext.Current.CancellationToken);
|
||||
Assert.Contains($"- [note.txt]({expectedUrl})", sentString);
|
||||
using var document = System.Text.Json.JsonDocument.Parse(sentString);
|
||||
var article = document.RootElement.GetProperty("article").GetString();
|
||||
Assert.Contains($"- [{originalName}]({expectedUrl})", article);
|
||||
// The regression shape: a relative, authority-less link.
|
||||
Assert.DoesNotContain("](/files/", sentString);
|
||||
Assert.DoesNotContain("](/files/", article);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
using Yavsc.Blogspot;
|
||||
using Yavsc.Api.Client;
|
||||
using Yavsc.Abstract.Files;
|
||||
using Yavsc.Server.Helpers;
|
||||
using AvaloniaEdit.Document;
|
||||
|
||||
namespace PostIt.ViewModels;
|
||||
|
|
@ -611,7 +612,8 @@ public partial class BlogsViewModel : ViewModelBase, IActionStatusViewModel
|
|||
|
||||
foreach (var attachment in attachments)
|
||||
{
|
||||
var relativePath = $"{EscapePathSegment(ownerSegment)}/blogs/{post.Id}/{EscapePathSegment(attachment.FileName)}";
|
||||
var storedName = AbstractFileSystemHelpers.FilterFileName(attachment.FileName);
|
||||
var relativePath = $"{EscapePathSegment(ownerSegment)}/blogs/{post.Id}/{EscapePathSegment(storedName)}";
|
||||
var fileUrl = ResolveUserFileUrl(relativePath);
|
||||
var markdownLine = $"- [{attachment.FileName}]({fileUrl})";
|
||||
|
||||
|
|
@ -636,7 +638,7 @@ public partial class BlogsViewModel : ViewModelBase, IActionStatusViewModel
|
|||
if (!string.IsNullOrWhiteSpace(authority)
|
||||
&& Uri.TryCreate(authority, UriKind.Absolute, out var baseUri))
|
||||
{
|
||||
return FileServerUrlHelpers.GetUserFilesUri(baseUri, relativePath).ToString();
|
||||
return FileServerUrlHelpers.GetUserFilesUri(baseUri, relativePath).AbsoluteUri;
|
||||
}
|
||||
|
||||
return $"{Yavsc.Constants.UserFilesPath}/{relativePath}";
|
||||
|
|
|
|||
Loading…
Reference in a new issue