javaNIO简单的下载图片

说明
因为对于JAVA NIO我用的不是特别熟练,所以此博客仅仅是我的学习笔记,写的不好,好望海涵。
备注: Global是一些公共的常量存储的类。

public static final String  BL_MODEL_URL="files_upload/bl_model/";
public static final String NOT_FOUND = "static/images/nopic.jpg";
public static final String NOT_FOUND = "static/images/nopic.jpg";
private static String BL_WEB_UPLOAD_PATH = "";
private static String BL_UPLOAD_PATH = "";
private static String BL_PREFIX_PATH = "uploads/";
private static String BL_MODEL_PATH = "";

public static String getWebUploadPath() {
		return BL_WEB_UPLOAD_PATH;
	}
	
public static void setWebUploadPath(String path) {
		if(!path.endsWith("/"))
			BL_WEB_UPLOAD_PATH = path + "/";
		else
			BL_WEB_UPLOAD_PATH = path;
	}
	
public static String getWebUploadPath() {
		return BL_WEB_UPLOAD_PATH;
	}
	
private static void getUploadPath() {
		String dir = "";
		if (StringUtils.isBlank(BL_UPLOAD_PATH)) {
			String uploadpath = getConfig("UPLOAD_PATH");
			if (StringUtils.isBlank(uploadpath)) {
				dir = BL_WEB_UPLOAD_PATH;
			}
			else
				dir = uploadpath;
			if(!dir.endsWith("/")) {
				dir += "/";
			}
			BL_UPLOAD_PATH = dir + BL_PREFIX_PATH;
			File file = new File(BL_UPLOAD_PATH);
			if (!file.exists())
				file.mkdirs();
		}
	}
	
public static String getUploadModelPath() {
		if (StringUtils.isBlank(BL_UPLOAD_PATH))
			getUploadPath();
		if (StringUtils.isBlank(BL_MODEL_PATH)) {
			BL_MODEL_PATH = BL_UPLOAD_PATH + "model/";
			File file = new File(BL_MODEL_PATH);
			if (!file.exists())
				file.mkdirs();
		}		
		return BL_MODEL_PATH;		
	}

以上就是NIO下载文件方法中定义的常量信息,至于Applog就是用来记录该方法启动时间的,如果想运行完全可以去掉,不必保留。

@RequestMapping(value="/pictureNIO")
	public void pictureNio(HttpServletRequest request,  
		      HttpServletResponse response, String mpid,String modelid
		       ) throws Exception { 
		// 设置文件输出类型
		 response.setContentType("image/jpeg");
		 ServletOutputStream op = response.getOutputStream();	
		 // 获取项目根目录
		 String path = request.getServletContext().getRealPath("/");

		 String downLoadPath = path + Global.BL_MODEL_PIC_URL + mpid;   
		 File file = new File(downLoadPath);
		 if(!file.exists()) {
		    	downLoadPath = path+Global.NOT_FOUND;
		    }
		 FileInputStream fileInputStream = new FileInputStream(file);
		 FileChannel fileChannel = fileInputStream.getChannel();
		 ByteBuffer bb = ByteBuffer.allocateDirect(2048);
		    byte[] barray = null;
		    int nRead=0;
		    try {
		        while ((nRead = fileChannel.read(bb)) >0) {
		            bb.flip();
		            barray = new byte[nRead];
		            bb.get(barray);
		            op.write(barray);
		            bb.clear();
		        /*  if (nRead == 0)
		            continue;		         
		         bb.position(0);
		          bb.limit(nRead);
		          while (bb.hasRemaining()) {
		            nGet = Math.min(bb.remaining(), bufferSize);
		            // read bytes from disk
		            bb.get(barray, 0, nGet);
		            // write bytes to output
		            op.write(barray);
		          }
		          bb.clear();*/
		        	
		        }
		      } catch (IOException e) {
		        e.printStackTrace();
		      } finally {
		        bb.clear();
		        fileChannel.close();
		        fileInputStream.close();
		      }
	}

首先我通过ServletOutputStream 获取到了响应的输出流,因为我之后会将读取到的信息放在其中(代码可能有点糙,并未做优化);通过前端传来的参数通过File判断该文件是否存在,不存在就返回404图片(NOT_FOUND是我在全局配置类中定义的静态常量,其中赋的是地址);如果存在,就通过FileInputStream 获取该图片,并打开输入通道;通道中的数据不为空,就将字节缓存中的数据放在字节数组中,写入数据流中。
在这里插入图片描述
通过JMeter接口压力测试,我发现在传输相同文件情况下,NIO平均的响应时间要比IO的慢,(我设置的线程组为1000,并发时间为20秒),也许是我写的NIO代码哪里写错了,影响了性能,毕竟我是第一次用NIO传输文件,所以请见谅。如果有更好的实现方法请一定,告诉我,我实现出来,并一定会接口压力测试一下,然后更新在博客中。

@RequestMapping(value="/pictureNIO")
	public void pictureNio(HttpServletRequest request,  
		      HttpServletResponse response, String mpid,String modelid
		       ) throws Exception { 
		long start = System.currentTimeMillis();
		String requestIp = request.getRemoteAddr();
		int intCode = 0;
		// 设置文件输出类型
		 response.setContentType("image/jpeg");
		 ServletOutputStream op = response.getOutputStream();	
		 String downLoadPath = Global.getUploadModelPath() + mpid;   
		 File file = new File(downLoadPath);
		 if(!file.exists()) {
			    intCode = Global.NO_DATA;
		    	downLoadPath = Global.getWebUploadPath() + Global.NOT_FOUND;
		    }
		 RandomAccessFile raf = new RandomAccessFile(file, "r");
		 FileChannel fileChannel = raf.getChannel();
		 long size = file.length();
		//将文件所有数据映射到虚拟内存,并只读
		MappedByteBuffer buff = fileChannel.map(FileChannel.MapMode.READ_ONLY ,0, fileChannel.size());
		byte[] by = new byte[(int) size];
		    try {
		    	for(int i =0;i<size;i++) {
		    		byte b = buff.get();
		    		by[i] = b;
		    	} 
		    	op.write(by);
		      } catch (Exception e) {
		    	  intCode = Global.IO_ERROR;
		        e.printStackTrace();
		      } finally {
		    	buff.clear();
		        fileChannel.close();
		        raf.close();
		        op.close();
		      }
		    long end = System.currentTimeMillis();
			long time = end - start;
			AppLog.insert("modelpic/picture", intCode, time, requestIp, dataSource);
	}

这是我经过改良过后的接口,速度比之前快了不少,并且我也做了测试,记录毫秒数。
同样是30.37 KB的文件,IO的速度要比NIO慢了超过10毫秒,不过对于同样的14.10KB的文件,两者相差不多。
在这里插入图片描述
这是我通过JMeter接口压力测试得出的结果,在1000个线程进行访问时,NIO平均每个请求的响应时间要比IO快,效率要高于IO,(文件大小为30.37 KB),如果有更好的改良请一定下方评论告诉我,我尽力实现出来,然后,并进行接口压力测试,来证明结论。

有人提议说使用Google的压缩插件将文件压缩一半试一试。
在这里插入图片描述
结果的确是快了,平均相应时间快了3毫秒。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值