diff --git a/spring-core/src/main/java/org/springframework/core/io/FileUrlResource.java b/spring-core/src/main/java/org/springframework/core/io/FileUrlResource.java index 9277bb39e2..99f0d95874 100644 --- a/spring-core/src/main/java/org/springframework/core/io/FileUrlResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/FileUrlResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -116,10 +116,7 @@ public class FileUrlResource extends UrlResource implements WritableResource { @Override public Resource createRelative(String relativePath) throws MalformedURLException { - if (relativePath.startsWith("/")) { - relativePath = relativePath.substring(1); - } - return new FileUrlResource(new URL(getURL(), relativePath)); + return new FileUrlResource(createRelativeURL(relativePath)); } } diff --git a/spring-core/src/main/java/org/springframework/core/io/UrlResource.java b/spring-core/src/main/java/org/springframework/core/io/UrlResource.java index 1d19bff59f..b989384a01 100644 --- a/spring-core/src/main/java/org/springframework/core/io/UrlResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/UrlResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -229,16 +229,31 @@ public class UrlResource extends AbstractFileResolvingResource { } /** - * This implementation creates a {@code UrlResource}, applying the given path - * relative to the path of the underlying URL of this resource descriptor. - * @see java.net.URL#URL(java.net.URL, String) + * This implementation creates a {@code UrlResource}, delegating to + * {@link #createRelativeURL(String)} for adapting the relative path. + * @see #createRelativeURL(String) */ @Override public Resource createRelative(String relativePath) throws MalformedURLException { + return new UrlResource(createRelativeURL(relativePath)); + } + + /** + * This delegate creates a {@code java.net.URL}, applying the given path + * relative to the path of the underlying URL of this resource descriptor. + * A leading slash will get dropped; a "#" symbol will get encoded. + * @since 5.2 + * @see #createRelative(String) + * @see java.net.URL#URL(java.net.URL, String) + */ + protected URL createRelativeURL(String relativePath) throws MalformedURLException { if (relativePath.startsWith("/")) { relativePath = relativePath.substring(1); } - return new UrlResource(new URL(this.url, relativePath)); + // # can appear in filenames, java.net.URL should not treat it as a fragment + relativePath = StringUtils.replace(relativePath, "#", "%23"); + // Use the URL constructor for applying the relative path as a URL spec + return new URL(this.url, relativePath); } /**