long res = dim.readLong();
System.out.println("res "+res);
//здесь ты приводишь long к int, и может произойти переполнение,
// и размерность массива будет отрицательной. Из-за этого вылетает эксепшн
byte[] byteArray = new byte[(int) res + 1];
во второй раз ты передаешь длину массива которую прочитал сервер
и опять ты урезал длину ограничив интом
File file = new File(basePath + "\\"+fileName);
//вот здесь ты обрезал получаемою длину файла, и от потока требуешь в будущем прочитать данные в этот массив
//но читаешь ты только кусок
//опять же здесь ты можешь снова получить отрицательное значение размерности массива
byte[] byteArray = new byte[(int) file.length()];
//и во второй раз ты передаешь длину ОБРЕЗАННОГО МАССИВА который в реальности смог прочитать здесь
bufferedInputStream.read(byteArray, 0, byteArray.length); // copied
не складируй данные в массив, передавай длину лонгом (или вообще не передавай , незачем она), а потом в цикле читай побайтово через read() (метод возвращает int - и как только он вернет -1 значит данные кончились) и сразу пиши в файл.