Reputation: 13
I am trying to learn how to upload and handle multiple files from a spring consumer (RestTemplate
) to a spring rest controller.
The Consumer
public static List<FileVerification> consume_post_multiple_files_upload(List<Path> paths) {
final String subAddress = "post_multiple_files_upload";
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
final MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
int counter = 1;
for (Path path : paths) {
final FileSystemResource fileSystemResource = new FileSystemResource(path.toString());
map.add("file_" + (counter++), fileSystemResource);
}
final HttpEntity<MultiValueMap<String, Object>> requestFilesEntity = new HttpEntity<MultiValueMap<String, Object>>(map, headers);
final RestTemplate restTemplate = new RestTemplate();
final ResponseEntity<List> listResponseEntity = restTemplate.postForEntity(CONSUMER_UPLOAD_TO_SERVER_ADDRESS + subAddress, requestFilesEntity, List.class);
return listResponseEntity.getBody();
}
The Controller
@RequestMapping(value = "post_multiple_files_upload", method = RequestMethod.POST)
public ResponseEntity<List<FileVerification>> post_multipleFilesUpload(@RequestParam(name = "file_1") MultipartFile multipartFile) throws IOException, NoSuchAlgorithmException {
GeneralConfig.createServerFileDirectory();
final List<FileVerification> serverFileVerificationsList = new ArrayList<>();
FileUtils.getMultipartFileInformation("post_multiple_files_upload", multipartFile).forEach(System.out::println);
final Path serverFile = GeneralConfig.getServerFileDirectoryPath().resolve(multipartFile.getOriginalFilename());
FileUtils.createFileAndWriteData(serverFile, multipartFile.getBytes());
serverFileVerificationsList.add(Factory.getFileVerification(serverFile));
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
GeneralConfig.deleteServerFileDirectory();
System.out.println();
return new ResponseEntity<List<FileVerification>>(serverFileVerificationsList, headers, HttpStatus.OK);
}
Test and Utility Code
@Test
public void test_consume_post_multiple_files_upload() throws IOException, NoSuchAlgorithmException {
final int fileCount = 10;
final List<Path> filesPaths = new ArrayList<>(fileCount);
final List<FileVerification> clientFileVerifications = new ArrayList<>(fileCount);
try {
for (int i = 0; i < fileCount; i++) {
final Path path = FileUtils.createRandomFileInClient();
filesPaths.add(path);
clientFileVerifications.add(Factory.getFileVerification(path));
}
final List<FileVerification> serverFileVerifications = consume_post_multiple_files_upload(filesPaths);
assertArrayEquals(clientFileVerifications.toArray(new FileVerification[0]), serverFileVerifications.toArray(new FileVerification[0]));
for (int i = 0; i < fileCount; i++) {
System.out.println("clientFileVerification#" + i + " = " + clientFileVerifications.get(i));
System.out.println("serverFileVerification#" + i + " = " + serverFileVerifications.get(i));
}
} finally {
for (Path filePath : filesPaths) {
Files.deleteIfExists(filePath);
}
}
}
-
import java.util.Arrays;
public class FileVerification {
private String fileName;
private byte[] digest_SHA256;
public FileVerification setFileName(String fileName) {
this.fileName = fileName;
return this;
}
public FileVerification setDigest_SHA256(byte[] digest_SHA256) {
this.digest_SHA256 = digest_SHA256;
return this;
}
public String getFileName() {
return this.fileName;
}
public byte[] getDigest_SHA256() {
return this.digest_SHA256;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FileVerification that = (FileVerification) o;
return this.fileName.equals(that.fileName) && Arrays.equals(this.digest_SHA256, that.digest_SHA256);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
for (byte b : digest_SHA256) {
builder.append(String.format("%02X", b));
}
final String digest_SHA256_representation = builder.toString();
return "FileVerification{fileName='" + this.fileName + '\'' + ", digest_SHA256='" + digest_SHA256_representation + '\'' + '}';
}
}
-
public static FileVerification getFileVerification(Path path) throws NoSuchAlgorithmException, IOException {
final MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
if (Files.notExists(path)) throw new IllegalArgumentException("file doesn't exist");
final byte[] digest = messageDigest.digest(Files.readAllBytes(path));
final String name = path.getFileName().toString();
return new FileVerification().setFileName(name).setDigest_SHA256(digest);
}
The Question What changes should be made to the consumer and/or the controller to allow for multiple files to be uploaded to the server?
Update : Problem solved, ill post the answer soon.
Upvotes: 0
Views: 3326
Reputation: 13
The Controller
@RequestMapping(value = "post_multiple_files_upload", method = RequestMethod.POST)
public ResponseEntity<List<FileVerification>> post_multipleFilesUpload(@RequestParam(name = "files") List<MultipartFile> multipartFiles) throws IOException, NoSuchAlgorithmException {
GeneralConfig.createServerFileDirectory();
final List<FileVerification> serverFileVerificationsList = new ArrayList<>();
int counter = 1;
for (MultipartFile multipartFile : multipartFiles) {
FileUtils.getMultipartFileInformation("post_multiple_files_upload#" + (counter++), multipartFile).forEach(System.out::println);
final Path serverFile = GeneralConfig.getServerFileDirectoryPath().resolve(multipartFile.getOriginalFilename());
FileUtils.createFileAndWriteData(serverFile, multipartFile.getBytes());
serverFileVerificationsList.add(Factory.getFileVerification(serverFile));
}
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
GeneralConfig.deleteServerFileDirectory();
System.out.println();
return new ResponseEntity<List<FileVerification>>(serverFileVerificationsList, headers, HttpStatus.OK);
}
The Consumer
public static List<FileVerification> consume_post_multiple_files_upload(List<Path> paths) {
final String subAddress = "post_multiple_files_upload";
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
final MultiValueMap<String, FileSystemResource> map = new LinkedMultiValueMap<>();
int counter = 1;
final List<FileSystemResource> fileSystemResourcesList = new ArrayList<FileSystemResource>();
for (Path path : paths) {
fileSystemResourcesList.add(new FileSystemResource(path.toString()));
}
map.put("files", fileSystemResourcesList);
final HttpEntity<MultiValueMap<String, FileSystemResource>> requestFilesEntity = new HttpEntity<MultiValueMap<String, FileSystemResource>>(map, headers);
final RestTemplate restTemplate = new RestTemplate();
final ResponseEntity<List<FileVerification>> fileVerificationListResponse = restTemplate.exchange(CONSUMER_UPLOAD_TO_SERVER_ADDRESS + subAddress, HttpMethod.POST, requestFilesEntity, new ParameterizedTypeReference<List<FileVerification>>() {
});
return fileVerificationListResponse.getBody();
}
Upvotes: 0
Reputation: 2479
Change you Controller.post_multipleFilesUpload
to:
public ResponseEntity<List<FileVerification>> post_multipleFilesUpload(@RequestParam(name = "file") List<MultipartFile> multipartFiles) throws IOException, NoSuchAlgorithmException {
Correspondingly, update consume_post_multiple_files_upload
to send all files with the same key (file
) by modifying the code to map.add("file", filesystemResourceList
) instead of adding each resource under its own separate key.
Upvotes: 1