Контроллер Spring Rest не работает для загрузки файла

Я пробовал отдых API без просмотра с mongodb. Мое приложение отлично работает со встроенным сервером загрузки Spring без ошибок. С автономным приложением tomcat работает без ошибок, но не может получить доступ к сопоставленному URL-адресу @RestController. Показывает 404 страница не найдена. Он не создает этот URL-адрес, но другой URL-адрес работает нормально.

Вот конфиг

FileStorageProperties.java

@Component
public class FileStorageProperties {
    private static String baseDir = "E://temp//FileManager//";
    private String uploadDir = "";

    public String getUploadDir() {
        return baseDir + uploadDir;
    }

    public void setUploadDir(String uploadDir) {
        this.uploadDir = baseDir + uploadDir;
    }
}

MediaTypeUtils.java

public class MediaTypeUtils {

    // abc.zip
    // abc.pdf,..
    public static MediaType getMediaTypeForFileName(ServletContext servletContext, String fileName) {
        // application/pdf
        // application/xml
        // image/gif, ...
        String mineType = servletContext.getMimeType(fileName);
        try {
            MediaType mediaType = MediaType.parseMediaType(mineType);
            return mediaType;
        } catch (Exception e) {
            return MediaType.APPLICATION_OCTET_STREAM;
        }
    }

}

Вот модель

Аватар.java:

@Document
@Component
public class Avatar {
    @Id
//  @Indexed(unique = true)
    private String id;
    private String originalName;
    @Indexed(unique = true)
    private String generatedName;
    private String size;
    @DBRef
    private User user;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getOriginalName() {
        return originalName;
    }

    public void setOriginalName(String originalName) {
        this.originalName = originalName;
    }

    public String getGeneratedName() {
        return generatedName;
    }

    public void setGeneratedName(String generatedName) {
        this.generatedName = generatedName;
    }

    public String getSize() {
        return size;
    }

    public void setSize(String size) {
        this.size = size;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Avatar [id=" + id + ", originalName=" + originalName + ", generatedName=" + generatedName + ", size="
                + size + ", user=" + user + "]";
    }


}

UploadFileResponse.java

public class UploadFileResponse {
    private String fileName;
    private String fileType;
    private long size;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getFileType() {
        return fileType;
    }

    public void setFileType(String fileType) {
        this.fileType = fileType;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public UploadFileResponse(String fileName, String fileType, long size) {
        this.fileName = fileName;
        this.fileType = fileType;
        this.size = size;
    }
}

FileStorageException.java

public class FileStorageException extends RuntimeException {
    /**
     * 
     */
    private static final long serialVersionUID = -2482390550398268830L;

    public FileStorageException(String message) {
        super(message);
    }

    public FileStorageException(String message, Throwable cause) {
        super(message, cause);
    }
}

MyFileNotFoundException.java

@ResponseStatus(HttpStatus.NOT_FOUND)
public class MyFileNotFoundException extends RuntimeException {
    /**
     * 
     */
    private static final long serialVersionUID = -7680896574598153059L;

    public MyFileNotFoundException(String message) {
        super(message);
    }

    public MyFileNotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}

Теперь репозиторий:

AvatarRepository.java

public interface AvatarRepository extends MongoRepository<Avatar, String>{

    public Avatar findAvatarByGeneratedName(String generatedName);
    public Avatar findAvatarByUser(User user);

}

AvatarRepositopryImpl.java. Существуют некоторые переопределенные методы MongoRepository, которые игнорируются в следующем коде, поскольку они вообще не используются.

@Repository
public class AvatarRepositopryImpl implements AvatarRepository {
    @Autowired
    MongoTemplate mongoTemplate;

    private static final String COLLECTION_NAME = "avatar";

    @Override
    public <S extends Avatar> List<S> saveAll(Iterable<S> entities) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<Avatar> findAll() {
        return mongoTemplate.findAll(Avatar.class, COLLECTION_NAME);
    }

    @Override
    public <S extends Avatar> S save(S entity) {
        return mongoTemplate.save(entity);
    }

    @Override
    public void deleteById(String id) {
        mongoTemplate.remove(id);
    }

    @Override
    public void delete(Avatar entity) {
        mongoTemplate.remove(entity);
    }

    @Override
    public Avatar findAvatarByGeneratedName(String generatedName) {
        Query query = new Query();
        query.addCriteria(Criteria.where("generatedName").is(generatedName));
        return (Avatar) mongoTemplate.findOne(query, Avatar.class);
    }

    @Override
    public Avatar findAvatarByUser(User user) {
//      System.out.println(user);
        Query query = new Query();
        query.addCriteria(Criteria.where("user").is(user));
        return (Avatar) mongoTemplate.find(query, Avatar.class);
    }

}

Вот мой сервис:

AvatarService.java

@Service
public class AvatarService {

    @Autowired
    private Avatar avatar;
//
//  @Autowired
//  private FileStorageService fileStorageService;

    @Autowired
    AvatarRepository avatarRepository;

    /**
     * @param fileStorageService
     * @param avatarRepository
     */

    public Avatar findAvatarByGeneratedName(String generatedName) {
        return avatarRepository.findAvatarByGeneratedName(generatedName);
    }

    public Avatar findAvatarByUser(User user) {
        System.out.println(user);
        return avatarRepository.findAvatarByUser(user);
    }

    public Avatar saveAvatar(User user,String fileOriginalName, String fileNameToSave, String fileSize) {
        avatar.setId(UUID.randomUUID().toString());
        avatar.setOriginalName(fileOriginalName);
        avatar.setGeneratedName(fileNameToSave);
        avatar.setSize(fileSize);
        avatar.setUser(user);

        return avatarRepository.save(avatar);
    }

    public void deleteAvatarByGeneratedName(String generatedName, Avatar avatar) {
        avatar = findAvatarByGeneratedName(generatedName);
        avatarRepository.deleteById(avatar.getId());
    }

AvatarManager.java

public class AvatarManager {

    AvatarService avatarService;

    @Autowired
    Avatar avatar;

    public AvatarManager(AvatarService avatarService) {
        this.avatarService = avatarService;
    }

    public String saveAvatar(User user, MultipartFile file) {
        deleteAvatarByUser(user);
        String[] ext = file.getOriginalFilename().split(Pattern.quote("."));
        String generatedName = new UUIDGenerator().generateId(avatar).toString() + "." + ext[ext.length - 1];
        avatarService.saveAvatar(user, file.getOriginalFilename(), generatedName, file.getSize() + "");
        new FileStorageService(new FileStorageProperties()).uploadFile(file, generatedName);
        new UploadFileResponse(generatedName, file.getContentType(), file.getSize());
        return generatedName;
    }

    public void deleteAvatar(String generatedName) {
        Avatar avatar = avatarService.findAvatarByGeneratedName(generatedName);
        if (avatar != null) {
            new FileStorageService(new FileStorageProperties()).deleteFile(generatedName);
            avatarService.deleteAvatarByGeneratedName(generatedName, avatar);
        }
    }

    public void deleteAvatarByUser(User user) {
//      System.out.println(user);
        avatar = avatarService.findAvatarByUser(user);
//      System.out.println(avatar.getGeneratedName());
        if (avatar != null) {
            deleteAvatar(avatar.getGeneratedName());
        }
    }

    public ResponseEntity<Resource> downloadAvatar(String avatarGeneratedName, HttpServletRequest request) {
//      System.out.println(request);
        return new FileStorageService(new FileStorageProperties()).downloadFile(avatarGeneratedName, request);
    }
}

Теперь Контроллер. Я даю два отображения. Первый не связан с файловым менеджером. Работает на обоих серверах. Другой работает на встроенном сервере с весенней загрузкой, но не на автономном коте. Он также не показывает никаких ошибок и не создает никаких URL-адресов.

Вот Controller.java;

@CrossOrigin(origins = { "*" })
@RestController
public class UserController {

    @Autowired
    EmployeeService employeeService;

    @Autowired
    UserService userService;

    @Autowired
    AvatarService avatarService;

    @Autowired
    BCryptPasswordEncoder passwordEncoder;

//It works on both server


@RequestMapping(value = "/login", method = RequestMethod.POST)
        public String loginEmployee(@RequestParam Map<String, String> data) {
            return new EmployeeManager(employeeService, userService)
                    .validateUserLogin(data.get("0").toString(), data.get("1"), passwordEncoder).toString();
        }

    //It doesn't work with standalone server
        @RequestMapping(value = "/edit-employee-profile", method = RequestMethod.POST)
    public void editProfileEmployee(@RequestParam(value = "avatar", required = false) MultipartFile file,
            @RequestParam(value = "user") String data) {
        JSONParser jp = new JSONParser(data);
        System.out.println(jp);
        LinkedHashMap<String, Object> userInfo;
        try {
            userInfo = jp.parseObject();
            User user = userService.findUserByEmail(userInfo.get("email").toString());
            System.out.println(user);
            user.setAvatarExistance(true);
            userService.updateUser(user);
//      Employee employee = employeeService.findEmployeeByUser(user);
            System.out.println(data);
            new EmployeeManager(employeeService, userService).employeeProfileEdit(data);
            if (file != null) {
                System.out.println(file);
                new AvatarManager(avatarService).saveAvatar(user, file);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
//      return "";
    }

person S.m. Abdul Wassae    schedule 21.11.2019    source источник
comment
Это может показаться очевидным, но запрос curl/postman, который приводит к ошибке 404, тоже может быть полезен.   -  person Ivan Baranuk    schedule 21.11.2019
comment
Есть ли у вас другие классы конфигурации для весны?   -  person Kamil Przybyo    schedule 21.11.2019
comment
Извините за неправильный контроллер. Теперь я отредактировал вопрос. Проект находится по указанной ссылке. drive.google.com/open?id=1PjGVp-hu2lFGjThy4WTrSV47yIWbdp6C   -  person S.m. Abdul Wassae    schedule 23.11.2019
comment
Вы загружаете содержимое файла в качестве параметра запроса (часть URL-адреса)?   -  person Markus Pscheidt    schedule 23.11.2019
comment
Спасибо ребята за участие. Я понял проблему с обработкой исключений в контроллере. Если я выполняю обработку исключений на контроллере, это не создает сопоставление URL-адресов, иначе все в порядке.   -  person S.m. Abdul Wassae    schedule 23.11.2019
comment
@MarkusPscheidt, да, и он работает нормально.   -  person S.m. Abdul Wassae    schedule 23.11.2019
comment
@S.m.AbdulWassae Вы не беспокоитесь о том, чтобы превысить безопасную максимальную длину URL-адреса (некоторые говорят, что 2048 символов, см. )?   -  person Markus Pscheidt    schedule 23.11.2019
comment
@MarkusPscheidt Спасибо за напоминание :) Может у вас есть предложения по решению этой проблемы? Должен ли он управляться из внешнего интерфейса?   -  person S.m. Abdul Wassae    schedule 23.11.2019


Ответы (1)


Отправьте файл как тело запроса (а не как параметр URL и @RequestParam), чтобы не превышать безопасную максимальную длину URL:

@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void uploadFile(ModelMap m, MultipartHttpServletRequest request) {

    MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
    List<MultipartFile> files = multiFileMap.isEmpty() ? null : multiFileMap.values().iterator().next();
    MultipartFile file = files != null && !files.isEmpty() ? files.get(0) : null;

    // ...
}
person Markus Pscheidt    schedule 23.11.2019
comment
Я думаю, что использовал сообщение там. Можете еще раз пересмотреть. :) Кстати, спасибо за напоминание. Следует ли избегать @RequestParam для файла MultipartFile. - person S.m. Abdul Wassae; 23.11.2019
comment
Вы правы, конечно, спасибо! См. исправленный ответ - person Markus Pscheidt; 23.11.2019