在开发过程中遇到了一个下载文件的问题,上传的时候有保存文件名称到数据库,但是文件名称改成了按时间命名的文件名,上传到ftp去了,然后现在的需求要在下载文件的名称要是原来上传的名称,这就要在下载的时候对文件重新命名。原来下载是不用经过后端的,直接在浏览器通过window.open(ftpUrl),直接指向ftp上的文件就可以了。
这时候要想重命名,就有两种方式,
- 方案一:要么在浏览器通过js下载文件后再修改名称给用户下载,
- 方案二:要么在java后端把文件下载回来,然后通过resonse返回浏览器下载
试了一下js下载并且重命名文件,好像可以,但是我现在的文件在ftp服务器上,跨域了,这种跨域问题无解,浏览器上有同源策略限制,所以在js上的XMLHttpRequest没有办法跨域。
参考:纯js实现文件下载并重命名功能
所以只能用方案二了,经过后端中转,后端服务器再去ftp下载文件,然后通过response输出到浏览器,然后页面端的代码直接修改为直接指向后端服务器而不是ftp服务器
window.open("<%=request.getContextPath()%>/fileApply/downloadFile?url="+encodeURI(ftpUrl)+"&fileName="+encodeURI(fileName));
顺便总结一下后端下载文件的两种方式
方式一:
@ResponseBody
@RequestMapping(value = "/downloadFile")
public void downloadFile(@RequestParam("url") String url,@RequestParam("fileName") String fileName,HttpServletResponse response){
try{
//获取要下载的文件
HttpResponse httpResponse = HttpUtil.executeHttpGet(url);
//ResponseEntity<Resource> entity = HttpClient.getRestTemplate().postForEntity(url, requestMsg, Resource.class);
if(httpResponse.getStatusLine().getStatusCode() == 200){
response.setCharacterEncoding("utf-8");
String contentType = httpResponse.getEntity().getContentType().getValue();
response.setContentType(contentType);
//设置文件名称
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
//ResponseEntity<Resource> entity.getBody().getInputStream()
//把文件的字节流写到response的outputStream里
StreamUtils.copy(httpResponse.getEntity().getContent(),response.getOutputStream());
response.getOutputStream().flush();
}
}catch (Exception e){
e.printStackTrace();
}finally{
try {
//必须关闭流,否则下载的文件会提示网络失败
response.getOutputStream().close();
} catch (IOException e) {}
}
}
方式二:
//ResponseEntity的返回方式是直接返回二进制的字节流给浏览器,不用原来的response
//服务器控制浏览器发下载方式打开文件,弊端就是失败时没有办法返回json
@RequestMapping(value = "/download")
public ResponseEntity<byte[]> download(@RequestParam("url") String url,@RequestParam("fileName") String fileName,HttpServletResponse response){
try{
//获取要下载的文件
HttpResponse httpResponse = HttpUtil.executeHttpGet(url);
if(httpResponse.getStatusLine().getStatusCode() == 200){
HttpHeaders headers = null;
ByteArrayOutputStream baos=null;
headers = new HttpHeaders();
//设置文件名称,服务器控制浏览器发下载方式打开文件,例:Content-Disposition: attachment; filename=aaa.jpg
headers.setContentDispositionFormData("attachment",new String(fileName.getBytes("UTF-8"), "iso-8859-1"));
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
baos = new ByteArrayOutputStream();
StreamUtils.copy(httpResponse.getEntity().getContent(),baos);
//直接返回二进制的字节流的response实体
return new ResponseEntity<byte[]>(baos.toByteArray(), headers, HttpStatus.CREATED);
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
HttpUtil的工具类
public static HttpResponse executeHttpGet(String url) {
HttpParams httpParameters = null;
HttpClient client = null;
HttpGet request = null;
try {
httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters,
timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
client = new DefaultHttpClient(httpParameters);
request = new HttpGet();
request.setURI(new URI(url));
HttpResponse response = client.execute(request);
return response;
} catch (Exception e) {
e.printStackTrace();
//LogUtils.e(TAG_TAG, "executeHttpGet: error=" + e.toString(), e);
return null;
} finally {
httpParameters = null;
client = null;
request = null;
}
}