SpringMVC 文件上传之 --- IO与NIO实现及其性能比较

来源:互联网 发布:一个淘宝店铺卖多少钱 编辑:程序博客网 时间:2024/05/17 00:19
SpringMVC文件上传之 IO 与 NIO 实现

我的Controller类:FileController.java

package aboo.controller;import aboo.bean.FileInfo;import aboo.service.FileService;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.util.FileCopyUtils;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.commons.CommonsMultipartFile;import javax.servlet.http.*;import java.io.*;import java.nio.*;import java.nio.channels.FileChannel;import java.util.List;/** * 文件的Controller * Created by admin on 2017/5/16. * * @author Aboo * */@Api(value = "文件的controller")@Controller@RequestMapping("/file")public class FileController {    private Logger log = LoggerFactory.getLogger(FileController.class);    @Autowired    private FileService fs;    /**     * 根据文件id下载文件  (IO)     * @param id  文件id,从url中取得     * @param request     * @param response     * @throws IOException  下载文件过程中,IO操作出现异常时,抛出异常     */    @ApiOperation(value = "下载文件",notes = "根据url里文件id来下载文件")    @RequestMapping(value="/download/{id}", method = RequestMethod.GET)    public void download(@PathVariable("id") Long id,HttpServletRequest request,HttpServletResponse response) throws IOException {        if (id != null && fs.exists(id)) {            FileInfo fileInfo = fs.findById(id);            String filename = fileInfo.getFile_name();            String realPath = request.getServletContext().getRealPath("WEB-INF/Files/");            File file = new File(realPath, filename);            if (file.exists()) {                response.setContentType(fileInfo.getMime_type());// 设置Content-Type为文件的MimeType                response.addHeader("Content-Disposition", "attachment;filename=" + filename);// 设置文件名                response.setContentLength((int) fileInfo.getLength());                //JAVA IO                InputStream inputStream = new BufferedInputStream(new FileInputStream(file));                //Copy bytes from source to destination(outputstream in this example), closes both streams.                FileCopyUtils.copy(inputStream, response.getOutputStream());                log.debug("download succeed! ---"+filename);            }        }else{            throw new Error("file who's id="+id+" is not exist!");        }    }    /**     * 根据文件id下载文件 (NIO)     * @param id  文件id,从url中取得     * @param request     * @param response     * @throws IOException  下载文件过程中,IO操作出现异常时,抛出异常     */    @ApiOperation(value = "下载文件",notes = "根据url里文件id来下载文件")    @RequestMapping(value="/nioDownload/{id}", method = RequestMethod.GET)    public void nioDownload(@PathVariable("id") Long id,HttpServletRequest request,HttpServletResponse response) throws IOException {        if (id != null && fs.exists(id)) {            FileInfo fileInfo = fs.findById(id);            String filename = fileInfo.getFile_name();            String realPath = request.getServletContext().getRealPath("WEB-INF/Files/");            File file = new File(realPath, filename);            if (file.exists()) {                response.setContentType(fileInfo.getMime_type());// 设置Content-Type为文件的MimeType                response.addHeader("Content-Disposition", "attachment;filename=" + filename);// 设置文件名                response.setContentLength((int) fileInfo.getLength());                //NIO 实现                int bufferSize = 131072;                FileInputStream fileInputStream = new FileInputStream(file);                FileChannel fileChannel = fileInputStream.getChannel();                // 6x128 KB = 768KB byte buffer                ByteBuffer buff = ByteBuffer.allocateDirect(786432);                byte[] byteArr = new byte[bufferSize];                int nRead, nGet;                try {                    while ((nRead = fileChannel.read(buff)) != -1) {                        if (nRead == 0) {                            continue;                        }                        buff.position(0);                        buff.limit(nRead);                        while (buff.hasRemaining()) {                            nGet = Math.min(buff.remaining(), bufferSize);                            // read bytes from disk                            buff.get(byteArr, 0, nGet);                            // write bytes to output                            response.getOutputStream().write(byteArr);                        }                        buff.clear();                        log.debug("download succeed! ---"+filename);                    }                } catch (IOException e) {                    e.printStackTrace();                } finally {                    buff.clear();                    fileChannel.close();                    fileInputStream.close();                }            }        }else{            throw new Error("file who's id="+id+" is not exist!");        }    }}

我的实体类:FileInfo.java


package aboo.bean;import javax.persistence.*;import java.io.Serializable;/** * 文件信息的实体类,与数据库表tab_file对应 * Created by admin on 2017/5/9. * @author Aboo * @see java.io.Serializable * */@Entity@Table(name = "tab_file")public class FileInfo implements Serializable{    private static final long serialVersionUID = 1L;    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    private Long id;    //自增id    private String file_name;    private long last_modified;    private String extension;    private long length;    private String mime_type;    public FileInfo() {    }    /**     * FileInfo的带参构造器,由于id为自动生成的类型,在此不接受此参数     *     * @param file_name 文件名     * @param last_modified 最后修改时间     * @param extension 文件扩展名     * @param length 文件长度(单位:byte)     * @param mime_type 文件的Mime类型     */    public FileInfo(String file_name, long last_modified, String extension, long length, String mime_type) {        this.file_name = file_name;        this.last_modified = last_modified;        this.extension = extension;        this.length = length;        this.mime_type = mime_type;    }    public Long getId() {        return id;    }    public String getFile_name() {        return file_name;    }    public void setFile_name(String file_name) {        this.file_name = file_name;    }    public long getLast_modified() {        return last_modified;    }    public void setLast_modified(long last_modified) {        this.last_modified = last_modified;    }    public String getExtension() {        return extension;    }    public void setExtension(String extension) {        this.extension = extension;    }    public String getMime_type() {        return mime_type;    }    public void setMime_type(String mime_type) {        this.mime_type = mime_type;    }    public long getLength() {        return length;    }    public void setLength(long length) {        this.length = length;    }    @Override    public String toString() {        return "FileInfo{" +                "id=" + id +                ", file_name='" + file_name + '\'' +                ", last_modified=" + last_modified +                ", extension='" + extension + '\'' +                ", length=" + length +                ", mime_type='" + mime_type + '\'' +                '}';    }}

我的JUnit Test:TestFileController.java


@WebAppConfiguration@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = {"classpath:applicationContext.xml","classpath:dispatcher-servlet.xml"})public class FileControllerTest {    private MockMvc mockMvc;    @Autowired    private WebApplicationContext wac;    private FileController fc;    @Before    public void setup(){        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();        fc = this.wac.getBean(FileController.class);    }       @Test    public void testDownload() throws Exception{        MockHttpServletRequest request = new MockMultipartHttpServletRequest();        MockHttpServletResponse response = new MockHttpServletResponse();        fc.download(95L,request,response);        System.out.println("tested download ...1");    }    @Test    public void testNioDownload() throws Exception{        MockHttpServletRequest request = new MockMultipartHttpServletRequest();        MockHttpServletResponse response = new MockHttpServletResponse();        fc.nioDownload(95L,request,response);        System.out.println("test nio download ---");    }    @Test    public void CompareTime() throws Exception{        MockHttpServletRequest request = new MockMultipartHttpServletRequest();        MockHttpServletResponse response = new MockHttpServletResponse();        long a = System.currentTimeMillis();            fc.download(95L,request,response);        long b = System.currentTimeMillis();        long c = System.currentTimeMillis();            fc.nioDownload(95L,request,response);        long d = System.currentTimeMillis();        System.out.println("io download takes :"+(b-a));        System.out.println("nio download takes :"+(d-c));    }}


我写了CompareTime() 方法,比较IO 和 NIO 所消耗的时间:

运行结果如下:

运行结果


最后,仅仅从时间上考虑的话,NIO的优势相当惊人的!!!

原创粉丝点击