【问题标题】:Spring rest controller not working for file upload弹簧休息控制器不适用于文件上传
【发布时间】:2020-03-17 11:05:30
【问题描述】:

我用 mongodb 尝试了一个没有任何 View 的 rest api。我的应用程序在 Spring Boot 嵌入式服务器上运行良好,没有错误。使用独立的 tomcat 应用程序运行时没有错误,但无法访问 @RestController 映射的 url。它显示 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;
        }
    }

}

这是模型

Avatar.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 + "]";
    }


}

上传文件响应.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);
    }
}

现在的控制器。我给出了两个映射。第一个不涉及文件管理器。它适用于两台服务器。另一个是在 Spring Boot 嵌入式服务器上工作,但不在独立的 tomcat 上。它也没有显示任何错误或创建任何 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 "";
    }

【问题讨论】:

  • 这听起来很明显,但导致 404 的 curl/postman 请求也很有用。
  • 你还有其他spring的配置类吗?
  • 对不起控制器错误。现在我已经编辑了这个问题。该项目在给定的链接上。 drive.google.com/open?id=1PjGVp-hu2lFGjThy4WTrSV47yIWbdp6C
  • 您是否将文件内容作为请求参数(URL 的一部分)上传?
  • 感谢大家的参与。我发现了控制器中异常处理的问题。如果我在控制器上进行异常处理,则不会创建该 url 映射,否则可以。

标签: java spring tomcat8 spring-restcontroller filehandler


【解决方案1】:

将文件作为请求正文(而不是 URL 参数和@RequestParam)发布,以不超过safe maximum URL length

@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;

    // ...
}

【讨论】:

  • 我想我在那里用过帖子。你可以再次修改。 :) 顺便说一句,感谢您的提醒。我应该避免 MultipartFile 文件的@RequestParam。
  • 你是对的,当然,谢谢!查看修改后的答案
猜你喜欢
  • 2020-09-25
  • 1970-01-01
  • 2017-09-01
  • 2020-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-21
  • 1970-01-01
相关资源
最近更新 更多