Я использую Spring boot MultipartFile, чтобы пользователи могли загружать свои файлы, и я хочу сохранить загруженные файлы в каталоге проекта или на моем диске «C:\upload» (или где бы он ни работал локально). Когда я отправляю любой файл, я получаю запрещенную ошибку 403. (для встроенного входа в систему используется spring-boot-starter-security).
Вот скриншот ошибки, напечатанной в браузере: 403 Error
В консоли получаю следующую ошибку:
org.thymeleaf.exceptions.TemplateInputException: ошибка разрешения шаблона [ошибка], шаблон может не существовать или может быть недоступен ни одному из настроенных преобразователей шаблонов
Это мой проект Структура: структура проекта
Это мой контроллер загрузки:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
public class UploadController {
//Save the uploaded file to this folder
private static String UPLOADED_FOLDER = "./src/main/resources/uploaded";
@GetMapping("/test")
public String index() {
return "upload";
}
@PostMapping("/upload")
public String singleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
return "redirect:uploadStatus";
}
try {
// Get the file and save it somewhere
byte[] bytes = file.getBytes();
Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(path, bytes);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + file.getOriginalFilename() + "'");
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/uploadStatus";
}
@GetMapping("/uploadStatus")
public String uploadStatus() {
return "uploadStatus";
}
}
Вот загрузка.html:
<!DOCTYPE html>
<html lang = "en" xmlns:th = "http://www.thymeleaf.org">
<body>
<h1>You can upload your files here</h1>
<form method = "POST" action = "/upload" enctype = "multipart/form-data">
<input type = "file" name = "file" /><br/><br/>
<input type = "submit" value = "Submit" />
</form>
</body>
</html>
uploadStatus.html:
<!DOCTYPE html>
<html lang = "en" xmlns:th = "http://www.thymeleaf.org">
<body>
<h1>Upload Status</h1>
<div th:if = "${message}">
<h2 th:text = "${message}"/>
</div>
</body>
</html>
Я использую тимелеаф в качестве механизма шаблонов:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Я все еще новичок и имею базовый опыт работы с весенней загрузкой, я некоторое время искал решение, поэтому, пожалуйста, любая помощь/предложение по решению проблемы будет высоко оценена.
Заранее спасибо!
Это ответ на ваш вопрос stackoverflow.com/questions/32064000/…?
Проверьте это и выясните, что может быть не так на вашей стороне: en.wikipedia.org/wiki/HTTP_403




Это связано с защитой CSRF (подделка межсайтовых запросов). Добавьте в форму скрытое поле с токеном CSRF.
<input type = "hidden" th:name = "${_csrf.parameterName}" th:value = "${_csrf.token}"/>
Большое спасибо @Gustlik, ваше решение мне очень помогло и решило проблему.
Проблема была из-за безопасности весенней загрузки (защита CSRF), для решения проблемы есть две возможности:
1- Добавление этой строки в форму загрузки работает нормально:
<input type = "hidden" th:name = "${_csrf.parameterName}" th:value = "${_csrf.token}"/>
2- Также можно было изменить автонастройку безопасности и сделать свою конфигурацию, чтобы отключить CSRF. Я использовал класс @Configuration следующим образом:
@Configuration
@EnableWebSecurity
public class configuration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable();
}
}
См. Настройка Spring Boot Security для подробного объяснения безопасности Spring Boot!
Большое спасибо @Gustlik
Не могли бы вы включить полную трассировку стека? Входит ли выполнение в блок catch?