Normalize filename for single file downloads

Closes gh-50087
This commit is contained in:
Andy Wilkinson
2026-04-16 11:20:34 +01:00
parent 43a593276f
commit 662fef2c83
4 changed files with 37 additions and 20 deletions
@@ -16,6 +16,7 @@
package org.springframework.boot.cli.command.init;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
@@ -242,7 +243,7 @@ class InitializrService {
value = value.substring(start + FILENAME_HEADER_PREFIX.length());
int end = value.indexOf('\"');
if (end != -1) {
return value.substring(0, end);
return new File(value.substring(0, end)).getName();
}
}
}
@@ -131,7 +131,7 @@ class ProjectGenerator {
}
private void writeProject(ProjectGenerationResponse entity, String output, boolean overwrite) throws IOException {
File outputFile = new File(output);
File outputFile = new File(System.getProperty("user.dir"), output);
if (outputFile.exists()) {
if (!overwrite) {
throw new ReportableException(
@@ -26,6 +26,7 @@ import java.util.zip.ZipOutputStream;
import joptsimple.OptionSet;
import org.apache.hc.core5.http.HttpHost;
import org.assertj.core.api.SoftAssertionsProvider.ThrowingRunnable;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
@@ -213,26 +214,30 @@ class InitCommandTests extends AbstractHttpClientMockTests {
@Test
void fileNotOverwrittenByDefault(@TempDir File tempDir) throws Exception {
File file = new File(tempDir, "test.file");
file.createNewFile();
long fileLength = file.length();
MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest("application/zip",
file.getAbsolutePath());
mockSuccessfulProjectGeneration(request);
assertThat(this.command.run()).as("Should have failed").isEqualTo(ExitStatus.ERROR);
assertThat(file.length()).as("File should not have changed").isEqualTo(fileLength);
withUserDir(tempDir, () -> {
File file = new File(tempDir, "test.file");
file.createNewFile();
long fileLength = file.length();
MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest("application/zip",
file.getAbsolutePath());
mockSuccessfulProjectGeneration(request);
assertThat(this.command.run()).as("Should have failed").isEqualTo(ExitStatus.ERROR);
assertThat(file.length()).as("File should not have changed").isEqualTo(fileLength);
});
}
@Test
void overwriteFile(@TempDir File tempDir) throws Exception {
File file = new File(tempDir, "test.file");
file.createNewFile();
long fileLength = file.length();
MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest("application/zip",
file.getAbsolutePath());
mockSuccessfulProjectGeneration(request);
assertThat(this.command.run("--force")).isEqualTo(ExitStatus.OK);
assertThat(fileLength).as("File should have changed").isNotEqualTo(file.length());
withUserDir(tempDir, () -> {
File file = new File(tempDir, "test.file");
file.createNewFile();
long fileLength = file.length();
MockHttpProjectGenerationRequest request = new MockHttpProjectGenerationRequest("application/zip",
file.getAbsolutePath());
mockSuccessfulProjectGeneration(request);
assertThat(this.command.run("--force")).isEqualTo(ExitStatus.OK);
assertThat(fileLength).as("File should have changed").isNotEqualTo(file.length());
});
}
@Test
@@ -399,6 +404,17 @@ class InitCommandTests extends AbstractHttpClientMockTests {
request.getHeaders("User-Agent")[0].getValue().startsWith("SpringBootCli/"))), isNull());
}
private void withUserDir(File userDir, ThrowingRunnable action) throws Exception {
String previous = System.getProperty("user.dir");
System.setProperty("user.dir", userDir.getAbsolutePath());
try {
action.run();
}
finally {
System.setProperty("user.dir", previous);
}
}
private byte[] createFakeZipArchive(String fileName, String content) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
try (ZipOutputStream zos = new ZipOutputStream(bos)) {
@@ -49,9 +49,9 @@ class InitializrServiceTests extends AbstractHttpClientMockTests {
void generateSimpleProject() throws Exception {
ProjectGenerationRequest request = new ProjectGenerationRequest();
MockHttpProjectGenerationRequest mockHttpRequest = new MockHttpProjectGenerationRequest("application/xml",
"foo.zip");
"nested/path/foo.zip");
ProjectGenerationResponse entity = generateProject(request, mockHttpRequest);
assertProjectEntity(entity, mockHttpRequest.contentType, mockHttpRequest.fileName);
assertProjectEntity(entity, mockHttpRequest.contentType, "foo.zip");
}
@Test