JAVA下载单个文件并且返回客户端,不写入本地

来源:互联网 发布:淘宝sdr是什么意思 编辑:程序博客网 时间:2024/05/23 14:49

@RestController
@RequestMapping("xxx")
public class DownLoadController {


/**
* 下载单个文件并且返回浏览器,不写入本地
* @return
*/
@RequestMapping("/multipleDownLoad")
public static void getFile(String url, String destFileName, HttpServletResponse httpServletResponse)
throws ClientProtocolException, IOException {
// 生成一个httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
InputStream in = entity.getContent();
try {
httpServletResponse.reset();
httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + destFileName + ".jpg");
httpServletResponse.setContentType("application/octet-stream; charset=utf-8");
OutputStream out = httpServletResponse.getOutputStream();
int l = 0;
byte[] tmp = new byte[1024];
/* while ((l = in.read(tmp)) != -1) {
out.write(tmp,0,1);
// 注意这里如果用OutputStream.write(buff)的话,图片会失真,大家可以试试
}*/
while ((l = in.read(tmp)) > 0) {
out.write(tmp, 0, l);
}
out.flush();
out.close();
} finally {
// 关闭低层流。
in.close();
}
httpclient.close();

}

}




改良版:为了解决ie不兼容问题,根据不同的浏览器,分别进行格式转换。

@SystemControllerLog(description="下载")@GetMapping(value="/oneDownLoad")public static void downLoadFile(String url, String destFileName, HttpServletResponse httpServletResponse)        throws ClientProtocolException, IOException {    // 生成一个httpclient对象    CloseableHttpClient httpclient = HttpClients.createDefault();    HttpGet httpget = new HttpGet(url);    HttpResponse response = httpclient.execute(httpget);    HttpEntity entity = response.getEntity();    InputStream in = entity.getContent();    String name = new String(destFileName.getBytes("utf-8"), "ISO-8859-1");    String type = url.substring(url.lastIndexOf(".")+1);    try {        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + name);        if("pdf".equals(type)) {            httpServletResponse.setContentType("application/pdf; charset=utf-8");        }else if("png".equals(type)) {            httpServletResponse.setContentType("image/png; charset=utf-8");        }else if("jpg".equals(type)) {            httpServletResponse.setContentType("image/jpg; charset=utf-8");        }        else if("jpeg".equals(type)) {            httpServletResponse.setContentType("image/jpeg; charset=utf-8");        }else {            httpServletResponse.setContentType("application/octet-stream; charset=utf-8");        }        OutputStream out = httpServletResponse.getOutputStream();        int l = 0;        byte[] tmp = new byte[1024];            /* while ((l = in.read(tmp)) != -1) {            out.write(tmp,0,1);            // 注意这里如果用OutputStream.write(buff)的话,图片会失真,大家可以试试            }*/        while ((l = in.read(tmp)) > 0) {            out.write(tmp, 0, l);        }        out.flush();        out.close();    } finally {        // 关闭低层流。        in.close();    }    httpclient.close();}


为了解决url中带空格的问题,进行局部转码,全部转码会造成httpGet不识别url,不认为是一个有效的http地址。


/** * 下载单个文件并且返回浏览器,不写入本地 * @return */@SystemControllerLog(description="下载")@GetMapping(value="/oneDownLoad")public static void downLoadFile(String url, String destFileName,HttpServletRequest req, HttpServletResponse httpServletResponse)        throws ClientProtocolException, IOException {    String userAgent = req.getHeader("user-agent").toLowerCase();    url = url.replace(destFileName,"");    String fileName = URLEncoder.encode(destFileName, "UTF-8");    if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {        // win10 ie edge 浏览器 和其他系统的ie        destFileName = URLEncoder.encode(destFileName, "UTF-8");    } else {        // fe        destFileName = new String(destFileName.getBytes("UTF-8"), "iso-8859-1");    }    // 生成一个httpclient对象    CloseableHttpClient httpclient = HttpClients.createDefault();    url = (url + fileName).replace("+","%20");    HttpGet httpget = new HttpGet(url);    HttpResponse response = httpclient.execute(httpget);    HttpEntity entity = response.getEntity();    InputStream in = entity.getContent();    String type = url.substring(url.lastIndexOf(".")+1);    try {        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + destFileName.replace("+"," "));        if("pdf".equals(type)) {            httpServletResponse.setContentType("application/pdf; charset=utf-8");        }else if("png".equals(type)) {            httpServletResponse.setContentType("image/png; charset=utf-8");        }else if("jpg".equals(type)) {            httpServletResponse.setContentType("image/jpg; charset=utf-8");        }        else if("jpeg".equals(type)) {            httpServletResponse.setContentType("image/jpeg; charset=utf-8");        }else {            httpServletResponse.setContentType("application/octet-stream; charset=utf-8");        }        OutputStream out = httpServletResponse.getOutputStream();        int l = 0;        byte[] tmp = new byte[1024];        while ((l = in.read(tmp)) > 0) {            out.write(tmp, 0, l);        }        out.flush();        out.close();    } finally {        // 关闭低层流。        in.close();    }    httpclient.close();}



改良版:为了解决上传文件本身的名字带“”+“”的问题,以及文件名称带空格的问题。
主要思想就是在前台传文件url以及名称的地方将有“+”的地方用正则表达式将用特殊字符代替,然后后端替换回去即可解决加号问题以及同时的空格问题。(后端进行encode会将空格转换为“”+“”,与文件名称中可能存在的“+”容易混淆。故而进行以下改良。)

前端:


/** * 文件下载  vue写法 * * @param  {String} url 要下载文件的地址 * @return {Object}     Promise */export const downLoadFile = (url, id = '', type = '') => {    let names = url.split('/')    let surl = process.env.BASE_API    url = url.replace(/\+/g,'*')    let name = names[names.length - 1].replace(/\+/g,'*')    let downurl = `${surl}/product/oneDownLoad?id=${id}&type=${type}&url=${url}&destFileName=${name}`    let win = window.open(downurl)}




/** * 下载单个文件并且返回浏览器,不写入本地 * @return */@SystemControllerLog(description="下载")@GetMapping(value="/oneDownLoad")public void downLoadFile(String url, String destFileName,HttpServletRequest req, HttpServletResponse httpServletResponse,String id,String type)        throws ClientProtocolException, IOException, SystemException {    String userAgent = req.getHeader("user-agent").toLowerCase();    url = url.replace(destFileName,"");    String fileName = URLEncoder.encode(destFileName, "UTF-8");    if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {        // win10 ie edge 浏览器 和其他系统的ie        destFileName = URLEncoder.encode(destFileName, "UTF-8");    } else {        // fe        destFileName = new String(destFileName.getBytes("UTF-8"), "iso-8859-1");    }    // 生成一个httpclient对象    CloseableHttpClient httpclient = HttpClients.createDefault();    url = (url + fileName).replace("+","%20");    destFileName = destFileName.replace("+","%20");    destFileName = destFileName.replace("*","+");    url = url.replace("*","+");    HttpGet httpget = new HttpGet(url);    HttpResponse response = httpclient.execute(httpget);    HttpEntity entity = response.getEntity();    InputStream in = entity.getContent();    String typeReq = url.substring(url.lastIndexOf(".")+1);    try {        httpServletResponse.setHeader("Content-Disposition", "attachment; filename=" + destFileName);        if("pdf".equals(typeReq)) {            httpServletResponse.setContentType("application/pdf; charset=utf-8");        }else if("png".equals(typeReq)) {            httpServletResponse.setContentType("image/png; charset=utf-8");        }else if("jpg".equals(typeReq)) {            httpServletResponse.setContentType("image/jpg; charset=utf-8");        }        else if("jpeg".equals(typeReq)) {            httpServletResponse.setContentType("image/jpeg; charset=utf-8");        }else {            httpServletResponse.setContentType("application/octet-stream; charset=utf-8");        }        OutputStream out = httpServletResponse.getOutputStream();        int l = 0;        byte[] tmp = new byte[1024];        while ((l = in.read(tmp)) > 0) {            out.write(tmp, 0, l);        }        out.flush();        out.close();    } finally {        // 关闭低层流。        in.close();    }    httpclient.close();}





原创粉丝点击