Uploading file to java server.

I send XMLHttpRequest from the client containing the same file to the RESTful service that receives the file, reads the first 1024 bytes, makes a hash with it using SHA-256, creates a directory with a triple nesting and temporarily writes the file, and then returns the path to it to the client.

Here is the corresponding code:

@POST @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(MediaType.APPLICATION_JSON) public Response uploadFile(@FormDataParam("file") InputStream is, @FormDataParam("file") FormDataContentDisposition fileDetail, @FormParam("type") String uploadType){ /* * Получаем имя загруженного файла, чтобы вытащить из него расширение * */ String oldFileName = fileDetail.getFileName(); String ext = oldFileName.substring(oldFileName.lastIndexOf(".")+1, oldFileName.length()); /* * Создаём строку и добавляем к ней путь загрузки всех файлов * */ StringBuilder newFileName = new StringBuilder(); OutputStream os = null; try { /* * Создаём буфер и читаем в него первые 1024 байта, * по ним мы будем хешировать файл * */ byte[] buffer = new byte[1024]; int read = is.read(buffer); HasherClass hasher = new HasherClass( HashType.SHA_256 ); String hash = hasher.hash(buffer); /* * Создаём директорию * */ newFileName.append(hash.substring(0, 2)).append(File.separator) .append(hash.substring(2, 4)).append(File.separator) .append(hash.substring(4,6)).append(File.separator); String dirPath = newFileName.toString(); File dir = new File(uploadPath + dirPath); if(!dir.exists()){ dir.mkdirs(); } /* * Создаем путь к самому файлу и проверяем на его несуществование, * если он существует, то возвращаем ошибку * */ String filePath = newFileName.append(hash.substring(6, hash.length())) .append(ext).toString(); File file = new File(uploadPath + filePath); if(file.exists()){ return Response.status(Response.Status.CONFLICT) .entity( Json.createObjectBuilder().add("exception", "Файл уже существует").build() ).build(); } /* * Создаём поток вывода и проверяем, если файл меньше 1024 байт, то пишет только буфер и возвращаем, * иначе пишем весь файл до конца * */ os = new FileOutputStream(file); if(read < 1024){ os.write(buffer, 0, read); }else{ while((read = is.read(buffer)) != -1){ os.write(buffer, 0, read); } } /* * Помечаем файл как временный, по истечению часа он будет удален, * если не используется * */ tempFiles.put(filePath, new Date()); }catch (IOException e) { Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity( Json.createObjectBuilder().add("exception", "Не удалось загрузить файл").build() ).build(); }finally { try { if(os != null) { os.flush(); os.close(); } }catch (IOException e){} } return Response.ok( Json.createObjectBuilder().add("fileName", newFileName.toString()) ).build(); } 

Also, the files are placed in a temporary directory, from which, after an hour, will be deleted by the daemon if not used.

When using this file (creating a post with images, changing the user's image) it will be deleted from the temporary directory, and also processed (for example, the image will be divided into 3 sizes and compressed before them), and placed in the main directory.

I have questions:

1) Is it correct to make a hash on the first 1024 bytes, or can it be done somehow in another way?

2) is it correct to create a temporary file and then move and process it

3) Other errors

Maybe someone more experienced will tell you what I'm doing wrong / what can be done better, correct, I will be very happy.

  • "otherwise we write the entire file to the end" - the error is lower, if in the buffer 1024 bytes, you are not writing the beginning of the file. - zRrr
  • How can you determine if a file is being used or not before deleting it? - Roman C
  • @RomanC, maybe I didn’t understand your question correctly, but the link to the temporary file will be only from the user who uploaded this file, and when he clicks to create a post or change the user’s images, then I will send a request to activate this file to the service, and the service will read the file, create 3 different resolutions, write them to the permanent storage, return links to the user and delete the temporary image - Eltsov Danil
  • @RomanC, I don’t immediately do image processing, for I’m afraid there will be a lot of unnecessary images that the user uploaded, but didn’t use - Eltsov Danil
  • @RomanC, maybe creating temporary files is unnecessary paranoia? - Eltsov Danil

0