JAVA web 上传图片至服务器(本地Linux服务器与Fastdfs)

需求:得到客户端上传的图片--转化为200尺寸一张。640一张。 加上原图三张。 
要求:将这三张图片保存到Linux一份,保存到Fasdfs一份
前提:客户端(js)图片压缩之后,用Base64编码格式之后上传过来。
实现:

首先得到图片的Base64编码的字符串。转化成byte[]数组

                         String imgData = request.getParameter( "imgData");// Base64的字符串
           BASE64Decoder decoder = new BASE64Decoder();
            byte[] imgByte = decoder.decodeBuffer(imgData);
            for ( int i = 0; i < imgByte. length; ++i) {
                 if (imgByte[i] < 0) { // 调整异常数据
                     imgByte[i] += 256;
                }
           }

首先看本地Linux服务器的:
思路:将图片的保存地址,以及访问的路径保存成一个配置文件。如下,其中fileDir是图片保存的路径,host是Linux服务器的主机名,fileStr是 fileDir路径暴漏出来的访问连接
#local_development_img_address
fileDir= /data/sites/up/img/
host= http://192.16.1.9
fileStr= /up/img/


因怕后期图片过多,导致文件夹里面的文件达到上限,所以在存储图片的时候,采用 YYMM/DD文件夹的方式。就是 年月/日,比如2016-01-04.  图片存储的路径则为配置文件中的fileDir+1601/04
所以先得到文件存储的完整路径:
     String endFile = DateUtil. endFileDir();  // 图片的根目录后面的文件夹目录(XXXX/XX(年月)/X(日))
     String imgSavePath =  fileDir  + endFile;  // 文件完整保存路径

这个endFileDir()的方法代码如下:
/**
      * 获得20150803 --> 15/8/3,15/12/6,15/2/15,15/10/3文件夹形式
      *
      * @param date
      * @return 15/10/3文件夹形式
      */
     public static String endFileDir () {
           Date date = new Date(System. currentTimeMillis());
           SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd" );
           String str = sdf.format(date).toString();
           StringBuffer sb = new StringBuffer();
            char[] timeArr = str.toCharArray();
           sb = sb.append(timeArr[2]).append(timeArr[3]);
            // str = ""+timeArr[2]+timeArr[3];
            if (timeArr[4] != '0') {
                sb = sb.append(timeArr[4]);
                 // str+=timeArr[4];
           }
           sb = sb.append(timeArr[5]).append( "/");
            // str+=""+timeArr[5]+"/";//根据当前系统环境确定分隔符
           
           
            //确定天数作为文件夹,测试部不需要天数,直接注释即可
            if(timeArr[6]!= '0'){
                sb = sb.append(timeArr[6]);
           }
           sb = sb.append(timeArr[7]).append( "/");
            return sb.toString().trim();
     }

 

    这个 imgSavePath  就是图片存储的完整路径。
  下一步是图片的名字: 图片的名字规则,一般为 yyyyMMddHHmmssSSS ,这个就不多说了。

  到这一步的时候,我们就可以到到图片暴漏出来的访问路径了。
  路径为:配置文件中的host+配置文件中的fileStr+endFile+图片的名字(图片的名字要包含图片后缀.png)
  比如:我的图片的名字为:20160104150412217 ,
  我存储Linux的文件路径为: /data/sites/up/img/ /1601/04/ 20160104150412217.png
  图片暴漏出来的访问路径为:  http://192.16.1.9 /up/img/ 20160104150412217.png


   然后调用下面的方法存储到Linux服务器:

  /**
      * @Title: uploadImg 上传的图片流
      * @param path 图片上传的路径
      * @param fileItem 图片文件
      * @return
      * @return: boolean
      */
     private static boolean uploadImg (String path, String imgName, byte[] imgByte) {
            // Linux服务器是反斜杠
           path=path.replaceAll( "/", "\\\\");
           File filePath = new File(path);
           filePath.setWritable( true, false);
            if (!filePath.exists()) {
                filePath.mkdirs();
           }
            boolean isSuccess = false;
           File file = new File(path + imgName);
           FileOutputStream output = null;
            try {
                output = new FileOutputStream(file);
                output.write(imgByte);
                output.flush();
                isSuccess = true;
           } catch (IOException e) {
                 // TODO Auto-generated catch block
                e.printStackTrace();
                isSuccess = false;
           } finally {
                 try {
                      if (output != null) {
                           output.close();
                     }
                } catch (IOException e) {
                      // TODO Auto-generated catch block
                     e.printStackTrace();
                }
           }
            return isSuccess;
     }


存入到FastDfs系统当中
先看一下FastDfs的配置文件:
connect_timeout = 2
network_timeout = 30
charset  = UTF-8
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = FastDFS1234567890
#可以配置多个tracker
tracker_server=172.16.1.9:22122

下一步:看代码,所有的操作都在代码里面,fastdfs会自动返回一个图片的访问路径,所以不用自己进行路径的拼接
调用方法:      String imgPath = FastUtil. uploadImg(imgByte,  IMG_FAST_SEXT  );

public class FastUtil {
     private static StorageClient storageClient;
     private static TrackerServer trackerServer;
     public static  final String FASTDFS_CONIFG="fdfs_client.conf" ;// Fastdfs的配置文件
     static {
            try {
                 // 初始化Fastdfs
                String path = new File(FastUtil.class.getResource("/" ).getFile()).getCanonicalPath();
                String confPath = path + File. separator +FASTDFS_CONIFG;
                ClientGlobal. init(confPath);
                TrackerClient tracker = new TrackerClient();
                 trackerServer = tracker.getConnection();
                StorageServer storageServer = null;
                 storageClient = new StorageClient( trackerServer, storageServer);
           } catch (IOException e) {
                e.printStackTrace();
           } catch (MyException e) {
                e.printStackTrace();
           }
     }
     /**
      * @Title: uploadImg
      * @Description:上传文件到fastdafs服务器
      * @param fileBuff 文件的字节数组
      * @param sExt   文件的后缀
      * @return
      * @return: String  返回该文件的路径
      */
     public static String uploadImg (byte [] fileBuff, String sExt) {
           String[] result = null;
            try {
                result = storageClient.upload_file(fileBuff, sExt,null);
           } catch (IOException e) {
                e.printStackTrace();
           } catch (MyException e) {
                e.printStackTrace();
           }
            if (result == null) {
                 return null;
           } else {
                String imgPath="http://"+trackerServer .getInetSocketAddress().getHostName()+"/"+result[0]+ "/"+result[1];
                 return imgPath;
           }
     }
}


上面,就得到图片存入到不同的服务器当中的图片访问路径了,下一步将图片的访问路径存入数据库,这一步操作就不讲解了

上面说到,还需要一个200尺寸的,一个640尺寸的,调用下面的方法就可以得到图片相对应的尺寸
 /**
      * @Title: scale
      * @Description: 将图片缩放成固定的宽和高
      * @param imgByte  缩放之后图片字节数组
      * @param width 缩放之后的宽度
      * @param height  高度
      * @return
      * @return: byte[] 根据宽高缩放之后的图片
      */
     private static byte[] scale (byte [] imgByte, int w, int h) {
            byte[] newImgByte = null;
            try {
                Image img = ImageIO. read(new ByteArrayInputStream(imgByte));
                 // 根据原图与要求的缩略图比例,找到最合适的缩略图比例
                 int width = img.getWidth( null);
                 int height = img.getHeight( null);
                 if ((width * 1.0) / w < (height * 1.0) / h) {
                      if (width > w) {
                           h = Integer. parseInt(new java.text.DecimalFormat("0" ).format(height * w / (width * 1.0)));
                     }
                } else {
                      if (height > h) {
                           w = Integer. parseInt(new java.text.DecimalFormat("0" ).format(width * h / (height * 1.0)));
                     }
                }
                BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Graphics g = bi.getGraphics();
                g.drawImage(img, 0, 0, w, h, null, null);
                g.dispose();
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                 if (w == 640) {
                     JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(byteArrayOutputStream);
                     JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(bi);
                     jep.setQuality(0.8f, true);
                     encoder.encode(bi, jep);
                } else {
                     ImageIO. write(bi, "PNG", byteArrayOutputStream);
                }
                newImgByte = byteArrayOutputStream.toByteArray();

           } catch (IOException e) {
                e.printStackTrace();
           }
            return newImgByte;
     }


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值