/**
* 从指定URL下载文件并保存到指定目录
* @param filePath 文件将要保存的目录
* @param method 请求方法,包括POST和GET
* @param name 文件名
* @param url 请求的路径
* @return
*/
public static File saveUrlAsFile(String url,String filePath,String method,String name) throws Exception{
String fileName = name; //为下载的文件命名
//创建不同的文件夹目录
File file=new File(filePath);
//判断文件夹是否存在
if (!file.exists())
{
//如果文件夹不存在,则创建新的的文件夹
file.mkdirs();
}
FileOutputStream fileOut = null;
HttpURLConnection conn = null;
InputStream inputStream = null;
// 建立链接
URL httpUrl=new URL(url);
conn=(HttpURLConnection) httpUrl.openConnection();
//以Post方式提交表单,默认get方式
conn.setRequestMethod(method);
conn.setDoInput(true);
conn.setDoOutput(true);
// post方式不能使用缓存
conn.setUseCaches(false);
//连接指定的资源
conn.connect();
//获取网络输入流
inputStream=conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(inputStream);
//判断文件的保存路径后面是否以/结尾
if (!filePath.endsWith("/")) {
filePath += "/";
}
//写入到文件(注意文件保存路径的后面一定要加上文件的名称)
fileOut = new FileOutputStream(filePath+fileName);
BufferedOutputStream bos = new BufferedOutputStream(fileOut);
byte[] buf = new byte[4096];
int length = bis.read(buf);
//保存文件
while(length != -1)
{
bos.write(buf, 0, length);
length = bis.read(buf);
}
bos.close();
bis.close();
conn.disconnect();
return file;
}
如此一来远程的服务资源就被成功保存到本地了
// 局部代码块
InputStream inputStream;
OutputStream outputStream;
File file1 = new File(filePath);
try {
if (file1.exists()){
response.setContentType(contentType+";charset=utf-8");
String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);
inputStream = new FileInputStream(filePath+"/"+courseName + "/" + fileName);
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
response.getOutputStream().write(bytes,0,len);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
//删除本地文件
deleteFile(file1);
}
public static void deleteFile(File file){
//判断文件不为null或文件目录存在
if (file == null || !file.exists()){
System.out.println("文件删除失败,请检查文件路径是否正确");
return;
}
//取得这个目录下的所有子文件对象
File[] files = file.listFiles();
//遍历该目录下的文件对象
for (File f: files){
//打印文件名
String name = file.getName();
//判断子目录是否存在子目录,如果是文件则删除
if (f.isDirectory()){
deleteFile(f);
}else {
f.delete();
}
}
//删除空文件夹 for循环已经把上一层节点的目录清空。
file.delete();
}
在获取服务器资源和后端提供下载的服务的时候都很顺利,但是在下载文件的时候,遇到文件名称带有中文就会出现问题!!
/** 上面代码省略,此处仅显示响应部分 */
response.setContentType(contentType+";charset=UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileName);
/** 下面代码相同,省略 */
这种做法可以正常下载:名字只包含数字和英文的文件,但是在遇到包含中文的文件,中文部分就会不显示并且连后缀都没有咯。
示例:本地要下载的文件名称(java基础语法.doc),点击下载后提示保存的文件名称(java),后缀也就都没有了。虽然说你可以手动把后缀给加上去后正常打开,但是体验感极差,况且,作为一个普通用户,并不知道你原文件的格式具体是什么。。
尝试了网上的各种也都不行
//例如1
finalFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
response.setHeader("Content-disposition", "attachment;filename="+finalFileName);
//例如2
response.setHeader("Content-disposition", "attachment;filename="+URLEncoder.encode(fileName,"UTF8"));
第一次完全没反应= =,带中文名称的文件下载下来和初代版本一样,捞不谈
第二种可以正常下载文件了,并且可以正常打开。但是下载过后文件名称出现乱码
#具体就是这种感觉
java基础语法.doc ——————————》java%32%512E%152113%12.doc (大概就是这种感觉)
虽说不影响使用,但是看起来及其难受
String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);
有效解决下载文件中文编码乱码问题。心累啊~
package com.jeesite.modules.study.entity.enums;
public enum FileSuffix {
DOC("doc", "application/msword"),
DOCX("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
XLS("xls", "text/xml"),
XLSX("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),
PPT("ppt", "application/vnd.ms-powerpoint"),
PPTX("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"),
PDF("pdf", "application/pdf"),
WPS("wps", "application/vnd.ms-works"),
TXT("txt", "text/plain"),
MP4("mp4", "video/mp4");
FileSuffix(String suffix, String contentType) {
this.suffix = suffix;
this.contentType = contentType;
}
private String suffix;
private String contentType;
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public static String getContentType(String suffix) {
FileSuffix[] values = FileSuffix.values();
for (FileSuffix item : values) {
if (item.getSuffix().equals(suffix)) {
return item.getContentType();
}
}
return null;
}
}
public void downloadOneFile(String id, HttpServletResponse response) throws Exception {
//指定下载到服务器的地址
String filePath = "/usr/local/files" + UUID.randomUUID() + "/";
//查询id对应的文件名称,地址,URL
Map<String, Object> file = stStudentService.downloadOneFile(id);
if (file != null) {
String fileName = file.get("fileName").toString();
if (file.get("fileName") != null && fileName.length() > 80) {
fileName = fileName.substring(0, 80);
}
String courseName = file.get("courseName").toString();
if (file.get("courseName") != null && courseName.length() > 80) {
courseName = courseName.substring(0, 80);
}
//文件路径
String fileUrl = file.get("fileUrl").toString();
String[] split = fileName.split("\\.");
//文件后缀
String suffix = split[split.length - 1];
//自定义枚举类,匹配 后缀名所对应的contentType
String contentType = FileSuffix.getContentType(suffix);
//获取并下载服务器资源到本地
DownloadFiles.saveUrlAsFile(fileUrl, filePath + "/" + courseName, "GET", fileName);
//提供本地下载服务
InputStream inputStream;
OutputStream outputStream;
File file1 = new File(filePath);
try {
if (file1.exists()){
response.setContentType(contentType+";charset=utf-8");
String fileNameURL = URLEncoder.encode(fileName,"UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);
inputStream = new FileInputStream(filePath+"/"+courseName + "/" + fileName);
outputStream = new BufferedOutputStream(response.getOutputStream());
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
response.getOutputStream().write(bytes,0,len);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
//删除本地文件,释放资源
deleteFile(file1);
}
}
}