大型网站对图片的下载,存放,及压缩管理
构建保存图片的路径:
1 String pathdir = "/images/product/"+ productTypeId+ "/"+ productId+ "/prototype";//构建文件保存的目录
为什么要有那么多个目录,因为java本身不会去获取图片,而是调用了操作系统的一些接口来获取图片,如果一个目录下图片太多的话,操作系统获取图片的速度会变慢 ,所以巴巴运动网在构建图片路径的时候搞了多个目录,分散保存图片。
有了这个pathdir就可以得到图片保存目录的真实路径:
1 String realpathdir = request.getSession().getServletContext().getRealPath(pathdir);
获取了图片的真实路径后,就可以开始保存图片了:
1 File savedir = new File(realpathdir); 2 File file = saveFile(savedir, filename, imagefile.getFileData());
imagefile为struts的FormFile类的对象,filename为文件名,这两个属性都可以从前台获取过来。以下是saveFile方法的代码:
1 /** 2 * 保存文件 3 * @param savedir 存放目录 4 * @param fileName 文件名称 5 * @param data 保存的内容 6 * @return 保存的文件 7 * @throws Exception 8 */ 9 public static File saveFile(File savedir, String fileName, byte[] data) throws Exception{ 10 if(!savedir.exists()) savedir.mkdirs();//如果目录不存在就创建 11 File file = new File(savedir, fileName); 12 FileOutputStream fileoutstream = new FileOutputStream(file); 13 fileoutstream.write(data); 14 fileoutstream.close(); 15 return file; 16 }
保存完图片后还要保存一张图片的缩略图,宽度为140px
View Code
这里我们用到了一个从网上下的用于压缩图片的ImageSizer工具类的静态方法,resize方法传进去的四个参数分别代表原始图片对象,需要被压缩的图片对象,压缩宽度的大小,图片后缀名。这个工具类只能压缩jpg, png, gif(非动画)三种格式,如果想压缩更多的格式需要付费。以下是该工具类:
1 /** 2 * 图像压缩工具 3 * @author lihuoming@sohu.com 4 * 5 */ 6 public class ImageSizer { 7 public static final MediaTracker tracker = new MediaTracker(new Component() { 8 private static final long serialVersionUID = 1234162663955668507L;} 9 ); 10 /** 11 * @param originalFile 原图像 12 * @param resizedFile 压缩后的图像 13 * @param width 图像宽 14 * @param format 图片格式 jpg, png, gif(非动画) 15 * @throws IOException 16 */ 17 public static void resize(File originalFile, File resizedFile, int width, String format) throws IOException { 18 if(format!=null && "gif".equals(format.toLowerCase())){ 19 resize(originalFile, resizedFile, width, 1); 20 return; 21 } 22 FileInputStream fis = new FileInputStream(originalFile); 23 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 24 int readLength = -1; 25 int bufferSize = 1024; 26 byte bytes[] = new byte[bufferSize]; 27 while ((readLength = fis.read(bytes, 0, bufferSize)) != -1) { 28 byteStream.write(bytes, 0, readLength); 29 } 30 byte[] in = byteStream.toByteArray(); 31 fis.close(); 32 byteStream.close(); 33 34 Image inputImage = Toolkit.getDefaultToolkit().createImage( in ); 35 waitForImage( inputImage ); 36 int imageWidth = inputImage.getWidth( null ); 37 if ( imageWidth < 1 ) 38 throw new IllegalArgumentException( "image width " + imageWidth + " is out of range" ); 39 int imageHeight = inputImage.getHeight( null ); 40 if ( imageHeight < 1 ) 41 throw new IllegalArgumentException( "image height " + imageHeight + " is out of range" ); 42 43 // Create output image. 44 int height = -1; 45 double scaleW = (double) imageWidth / (double) width; 46 double scaleY = (double) imageHeight / (double) height; 47 if (scaleW >= 0 && scaleY >=0) { 48 if (scaleW > scaleY) { 49 height = -1; 50 } else { 51 width = -1; 52 } 53 } 54 Image outputImage = inputImage.getScaledInstance( width, height, java.awt.Image.SCALE_DEFAULT); 55 checkImage( outputImage ); 56 encode(new FileOutputStream(resizedFile), outputImage, format); 57 } 58 59 /** Checks the given image for valid width and height. */ 60 private static void checkImage( Image image ) { 61 waitForImage( image ); 62 int imageWidth = image.getWidth( null ); 63 if ( imageWidth < 1 ) 64 throw new IllegalArgumentException( "image width " + imageWidth + " is out of range" ); 65 int imageHeight = image.getHeight( null ); 66 if ( imageHeight < 1 ) 67 throw new IllegalArgumentException( "image height " + imageHeight + " is out of range" ); 68 } 69 70 /** Waits for given image to load. Use before querying image height/width/colors. */ 71 private static void waitForImage( Image image ) { 72 try { 73 tracker.addImage( image, 0 ); 74 tracker.waitForID( 0 ); 75 tracker.removeImage(image, 0); 76 } catch( InterruptedException e ) { e.printStackTrace(); } 77 } 78 79 /** Encodes the given image at the given quality to the output stream. */ 80 private static void encode( OutputStream outputStream, Image outputImage, String format ) 81 throws java.io.IOException { 82 int outputWidth = outputImage.getWidth( null ); 83 if ( outputWidth < 1 ) 84 throw new IllegalArgumentException( "output image width " + outputWidth + " is out of range" ); 85 int outputHeight = outputImage.getHeight( null ); 86 if ( outputHeight < 1 ) 87 throw new IllegalArgumentException( "output image height " + outputHeight + " is out of range" ); 88 89 // Get a buffered image from the image. 90 BufferedImage bi = new BufferedImage( outputWidth, outputHeight, 91 BufferedImage.TYPE_INT_RGB ); 92 Graphics2D biContext = bi.createGraphics(); 93 biContext.drawImage( outputImage, 0, 0, null ); 94 ImageIO.write(bi, format, outputStream); 95 outputStream.flush(); 96 } 97 98 /** 99 * 缩放gif图片 100 * @param originalFile 原图片 101 * @param resizedFile 缩放后的图片 102 * @param newWidth 宽度 103 * @param quality 缩放比例 (等比例) 104 * @throws IOException 105 */ 106 private static void resize(File originalFile, File resizedFile, int newWidth, float quality) throws IOException { 107 if (quality < 0 || quality > 1) { 108 throw new IllegalArgumentException("Quality has to be between 0 and 1"); 109 } 110 ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath()); 111 Image i = ii.getImage(); 112 Image resizedImage = null; 113 int iWidth = i.getWidth(null); 114 int iHeight = i.getHeight(null); 115 if (iWidth > iHeight) { 116 resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight) / iWidth, Image.SCALE_SMOOTH); 117 } else { 118 resizedImage = i.getScaledInstance((newWidth * iWidth) / iHeight, newWidth, Image.SCALE_SMOOTH); 119 } 120 // This code ensures that all the pixels in the image are loaded. 121 Image temp = new ImageIcon(resizedImage).getImage(); 122 // Create the buffered image. 123 BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null), 124 BufferedImage.TYPE_INT_RGB); 125 // Copy image to buffered image. 126 Graphics g = bufferedImage.createGraphics(); 127 // Clear background and paint the image. 128 g.setColor(Color.white); 129 g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null)); 130 g.drawImage(temp, 0, 0, null); 131 g.dispose(); 132 // Soften. 133 float softenFactor = 0.05f; 134 float[] softenArray = {0, softenFactor, 0, softenFactor, 1-(softenFactor*4), softenFactor, 0, softenFactor, 0}; 135 Kernel kernel = new Kernel(3, 3, softenArray); 136 ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); 137 bufferedImage = cOp.filter(bufferedImage, null); 138 // Write the jpeg to a file. 139 FileOutputStream out = new FileOutputStream(resizedFile); 140 // Encodes image as a JPEG data stream 141 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 142 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage); 143 param.setQuality(quality, true); 144 encoder.setJPEGEncodeParam(param); 145 encoder.encode(bufferedImage); 146 } 147 }
允许用户上传文件,那么我们一定要注意安全,如果用户上传了一个jsp文件,而这个文件的上传路径恰好能被用户访问到,那么用户可能会在这个jsp文件里面做一个对网站其他文件的文件操作,可以将文件保存到web-inf下面,如果用户需要下载,我们就写一个servlet读取这个文件,以流的方式返回给用户。