package communication.filetransfer; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Base64; import java.util.List; import javax.imageio.ImageIO; import messages.MessageFichier; import messages.MauvaisTypeMessageException; import messages.Message.TypeMessage; public class FileTransferUtils { // Relative path of the folder where are put the received files protected static final String DOWNLOADS_RELATIVE_PATH = "../downloads/"; protected static final ArrayList IMAGE_EXTENSIONS = new ArrayList( List.of("tif", "tiff", "bmp", "jpg", "jpeg", "gif", "png", "eps", "svg")); protected static final int KB_SIZE = 1024; /** * Process what to display on the chat depending on the file sent/received. A * thumbnail will be created in the case of an image, A String with the file's * name will be created otherwise. * * @param file The file to process. * @return A message of which content is either a thumbnail or the file's name. * @throws IOException */ protected static MessageFichier processMessageToDisplay(File file) throws IOException { String nameFile = file.getName(); String extension = processFileExtension(nameFile); TypeMessage type; String contenu; if (IMAGE_EXTENSIONS.contains(extension)) { type = TypeMessage.IMAGE; BufferedImage img = ImageIO.read(file); contenu = encodeImage(createThumbnail(img), extension); } else { type = TypeMessage.FICHIER; contenu = nameFile; } try { return new MessageFichier(type, contenu, extension); } catch (MauvaisTypeMessageException e) { e.printStackTrace(); } return null; } /** * @param fileName The name of the file (with its extension). * @return The extension of the file. */ protected static String processFileExtension(String fileName) { String extension = ""; int i = fileName.indexOf('.'); if (i >= 0 || i != -1) { extension = fileName.substring(i + 1).toLowerCase(); } return extension; } /** * @param image A buffered image. * @return A thumbnail of the image. */ private static BufferedImage createThumbnail(BufferedImage image) { float w = image.getWidth(); float ratio = (w > 150) ? (150F / w) : 1; BufferedImage scaled = scale(image, ratio); return scaled; } /** * @param img A buffered image. * @param extension The extension of the image. * @return The base64 encoded string corresponding to the given image. * @throws IOException */ private static String encodeImage(BufferedImage img, String extension) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(img, extension, bos); String imgString = Base64.getEncoder().encodeToString(bos.toByteArray()); bos.close(); return imgString; } /** * @param imageString The base64 encoded string of an image. * @return A buffered image corresponding to the given base64 encoded string. * @throws IOException */ public static BufferedImage decodeImage(String imageString) throws IOException { byte[] imgData = Base64.getDecoder().decode(imageString); InputStream is = new ByteArrayInputStream(imgData); BufferedImage img = ImageIO.read(is); is.close(); return img; } // Used to scale an image with a given ratio private static BufferedImage scale(BufferedImage source, double ratio) { int w = (int) (source.getWidth() * ratio); int h = (int) (source.getHeight() * ratio); BufferedImage bi = getCompatibleImage(w, h); Graphics2D g2d = bi.createGraphics(); double xScale = (double) w / source.getWidth(); double yScale = (double) h / source.getHeight(); AffineTransform at = AffineTransform.getScaleInstance(xScale, yScale); g2d.drawRenderedImage(source, at); g2d.dispose(); return bi; } private static BufferedImage getCompatibleImage(int w, int h) { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice gd = ge.getDefaultScreenDevice(); GraphicsConfiguration gc = gd.getDefaultConfiguration(); BufferedImage image = gc.createCompatibleImage(w, h); return image; } /** * Create the folder with the path "DOWNLOADS_RELATIVE_PATH" if it does not * exist. */ public static void createDownloads() { File downloads = new File(FileTransferUtils.DOWNLOADS_RELATIVE_PATH); if (!downloads.exists()) { downloads.mkdir(); } } }