package org.smartly.commons.network.socket.messages.tools; import org.smartly.IConstants; import org.smartly.commons.io.filetokenizer.FileTokenizer; import org.smartly.commons.network.socket.messages.UserToken; import org.smartly.commons.network.socket.messages.multipart.Multipart; import org.smartly.commons.network.socket.messages.multipart.MultipartMessagePart; import org.smartly.commons.util.FileUtils; import org.smartly.commons.util.PathUtils; import org.smartly.commons.util.StringUtils; import java.io.File; import java.io.IOException; /** * Utility methods for multipart messages. */ public class MultipartMessageUtils { public static final String STORE = PathUtils.getTemporaryDirectory("chunks"); /** * Save single part message on disk (temporary folder) and replace PartName with output file name. * If error occurred, PartName is replaced with "NULL" (string) and exception is added to Error field. * If par has no data, PartName is replaced with "NULL" (string). * * @param part Part to save on disk. */ public static long saveOnDisk(final MultipartMessagePart part) { if (part.hasData()) { try { final long length = part.getDataLength(); final String root = PathUtils.concat(STORE, part.getUid()); // ensure directory exists FileUtils.tryMkdirs(root); final String output = PathUtils.concat(root, PathUtils.getFilename(part.getInfo().getPartName())); FileUtils.copy(part.getDataBytes(), new File(output)); part.getInfo().setPartName(output); return length; } catch (Throwable t) { part.getInfo().setPartName(IConstants.NULL); part.setError(t); } finally { part.clearData(); // remove data to free memory on MultipartPool } } else { // no data in this part part.getInfo().setPartName(IConstants.NULL); } return 0; } /** * Join all parts in a single file and remove temporary files. * * @param multipart Multipart to save on disk */ public static String saveOnDisk(final Multipart multipart, final String outputPath) throws Exception { if (null != multipart && StringUtils.hasText(outputPath) && multipart.isFull()) { final Throwable partError = multipart.getError(); if (null == partError) { // ensure directory exists FileUtils.tryMkdirs(outputPath); // get output filename and join chunks final String partName = multipart.getName(); final String outputFile; if (PathUtils.isDirectory(outputPath)) { if (StringUtils.hasText(partName)) { outputFile = PathUtils.concat(outputPath, partName); } else { outputFile = PathUtils.concat(outputPath, "new_file"); } } else { outputFile = outputPath; } final String[] names = multipart.getPartNames(); FileTokenizer.join(names, outputFile, null); // remove temp FileUtils.delete(PathUtils.getParent(names[0])); return outputFile; } else { try { remove(multipart); } catch (Throwable ignored) { } throw new Exception(partError); } } return ""; } public static void remove(final Multipart multipart) throws IOException { final String[] names = multipart.getPartNames(); if (names.length > 0) { FileUtils.delete(names); FileUtils.delete(PathUtils.getParent(names[0])); } } public static void setPartBytes(final MultipartMessagePart part) { try { final UserToken userToken = new UserToken(part.getUserToken()); final String sourceName = userToken.getSourceAbsolutePath(); if (FileUtils.exists(sourceName)) { final int index = part.getInfo().getIndex(); final long chunkSize = part.getInfo().getPartLength(); part.setData(FileUtils.copyToByteArray(new File(sourceName), index * chunkSize, chunkSize)); } } catch (final Throwable t) { part.setError(t); } } }