javaarraysspringrestspring-framework-beans

Spring Framework: Byte Array is corrupted when received


I want to create a file upload system that works with byte arrays using Spring Framework. I have a controller as below:

@Controller
public class FileUploadController {

    @Autowired
    FileUploadService fileService;

    @GetMapping("/")
    public void index() {
        System.out.println("Show Upload Page");
    }

    @PostMapping("/")
    public void uploadFile(@RequestParam("file") byte[] file, @RequestParam("fileName")String fileName, @RequestParam("fileType") String fileType, RedirectAttributes redirectAttributes) {

        try {

            HashMap<String, String> result = fileService.saveFile(file,fileName,fileType);
            String filePath = result.get("filePath");
            String fileSize = result.get("fileSize");

            System.out.println("Path " + filePath + " " + fileSize + " Bytes");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

and a service like so:

@Service
public class FileUploadService {

    @Value("${app.upload.dir:${user.home}}")
    public String uploadDir;

    public HashMap<String, String> saveFile(byte[] file, String fileName, String fileType) throws Exception {

        try {
            Path copyLocation = Paths
                    .get(uploadDir + File.separator + StringUtils.cleanPath(fileName));
            String pathString = copyLocation.toString();
            FileOutputStream stream = new FileOutputStream(pathString);
            stream.write(file);
            String fileSize = String.valueOf(Files.size(copyLocation));
            HashMap<String, String> result = new HashMap<String, String>();
            result.put("filePath", pathString);
            result.put("fileSize", fileSize);

            return result;

        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("Could not store file " + fileName
                    + ". Please try again!");
        }

    }

}

And I am testing this API using this code which uses Apache HttpClient:

public class app {

        public static void main(String[] args) throws IOException, InterruptedException {

            byte[] array = Files.readAllBytes(Paths.get("/Users/hemodd/Desktop/test-pic.png"));

            CloseableHttpClient client = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost("http://localhost:8080");

            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.addTextBody("fileName", "Newwwww");
            builder.addTextBody("fileType", "png");
            builder.addBinaryBody("file", array);

            HttpEntity multipart = builder.build();
            httpPost.setEntity(multipart);

            CloseableHttpResponse response = client.execute(httpPost);
            client.close();
        }
    }

Now, the problem is that the result of the writing of the received byte array is a corrupted file. I don't want to use MultipartFile and I need to stick with byte arrays. Any help is appreciated.


Solution

  • The problem is with passing file in your controller: @RequestParam("file") byte[] file

    You have several options:

    Your test app creates and sends a multipart request. For sending byte array in body you have to change it to:

    HttpEntity entity = new ByteArrayEntity(array);
    httpPost.setEntity(entity);