在程序开发过程中,不免遇到用户端需要请求下载服务端图片需求。这种需求就是流的读写,从输入流中读取,从输出流中写出,整个过程称为拷贝。以下是对文件下载需求的接口实现。

下载服务器本地文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void down(HttpServletResponse response) throws Exception {  
String path = "Q:\\测试文件.md";
File file = new File(path);
// 文件名称
String name = file.getName();
// 处理文件名称编码以免乱码
String encodedName = URLEncoder.encode(name, "UTF-8").replace("+", "%20");
// 文件后缀
String suffix = name.substring(name.lastIndexOf(".") + 1);
// 将文件读入文件流
FileInputStream fileInputStream = new FileInputStream(file);
response.reset();
response.setContentType(ContentTypeEnum.valueOfCode(suffix));
response.addHeader("Content-Disposition", "attachment; filename=\"" + encodedName + "\"");
byte[] bytes = new byte[1024];
int length;
try {
while ((length = fileInputStream.read(bytes)) > 0) {
response.getOutputStream().write(bytes,0, length);
}
fileInputStream.close();
} catch (IOException e) {}
}

下载网络文件或在线打开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void downChannel(boolean down, HttpServletResponse response) throws Exception {  
String url = "https://img0.baidu.com/it/u=1058961982,3919091402&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1728838800&t=73de5c7aca4f346bdcef40a041324922";
// 自定义文件名称
String fileName = "downloaded_image.jpg";
response.reset();
response.setContentType("image/jpeg");
if (down) {
response.addHeader("Content-Disposition", "attachment; filename=" + fileName);
} else {
response.setHeader("Content-Disposition", "inline; filename=" + fileName);
}
ServletOutputStream outputStream = response.getOutputStream();
long download = HttpUtil.download(url, outputStream, false);
System.out.println("文件大小: " + download);
}

压缩下载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void downChannel(HttpServletResponse response) throws Exception {  
// 配置 response String zipName = "数据.zip";
response.reset();
response.setContentType("application/zip; charset=UTF-8");
String encodedZipName = URLEncoder.encode(zipName, "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedZipName + "\"");
try (ServletOutputStream outputStream = response.getOutputStream();
ZipOutputStream zipos = new ZipOutputStream(new BufferedOutputStream(outputStream))){
zipos.setMethod(ZipOutputStream.DEFLATED);
List<String> fileList = Arrays.asList("https://img2.baidu.com/it/u=2749871286,2317752756&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1729098000&t=8651d2711ae32a3886955d79083c6a67",
"https://img2.baidu.com/it/u=595890530,1990525612&fm=253&fmt=auto?w=800&h=800",
"https://img1.baidu.com/it/u=294940611,1850369177&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1729098000&t=27ad7e93e09e6d652c8d1053492cce4a");
// 设置压缩流
for (int i = 0; i < fileList.size(); i++) {
String urlStr = fileList.get(i);
String name = "图片" + i + ".jpg";
zipos.putNextEntry(new ZipEntry(name));
try (InputStream inputStream = new URL(urlStr).openStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
zipos.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
zipos.closeEntry();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

响应头常见枚举类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
@Getter  
@AllArgsConstructor
public enum ContentTypeEnum {

/**
* PDF */ PDF("pdf", "application/pdf"),

/**
* DOC */ DOC("doc", "application/msword"),

/**
* DOCX */ DOCX("docx", "application/msword"),

/**
* XLS */ XLS("xlsx", "application/vnd.ms-excel"),

/**
* XLSX */ XLSX("xlsx", "application/vnd.ms-excel"),

/**
* PPT */ PPT("ppt", "application/vnd.ms-powerpoint"),

/**
* PPTX */ PPTX("pptx", "application/vnd.ms-powerpoint"),

/**
* PNG */ PNG("png", "image/png"),

/**
* JPG */ JPG("jpg", "image/jpeg"),

/**
* JPEG */ JPEG("jpeg", "image/jpeg"),

/**
* GIF */ GIF("gif", "image/gif"),

/**
* BMP */ BMP("bmp", "image/bmp"),

/**
* ZIP */ ZIP("zip", "application/zip"),

/**
* RAR */ RAR("rar", "application/x-rar-compressed"),

/**
* GZ */ GS("gz", "application/gzip"),

/**
* TAR_GZ */ TAR_GZ("tar.gz", "application/gzip"),

/**
* mp3 */ MP3("mp3", "audio/mpeg"),

/**
* mp4 */ MP4("mp4", "video/mp4"),

/**
* AVI */ AVI("avi", "video/x-msvideo"),

/**
* TXT */ TXT("txt", "video/x-msvideo"),

/**
* html */ HTML("html", "text/html"),

/**
* htm */ HTM("htm", "text/html"),

/**
* xml */ XML("xml", "application/xml"),

/**
* JSON */ JSON("json", "application/json"),

/**
* CSV */ CSV("csv", "text/csv"),

/**
* EXE */ EXE("exe", "application/octet-stream"),

/**
* JAR */ JAR("jar", "application/java-archive"),

/**
* CLASS */ CLASS("class", "application/octet-stream"),

/**
* BAT */ BAT("bat", "application/octet-stream"),

/**
* SH */ SH("sh", "application/octet-stream"),

/**
* PROPERTIES */ PROPERTIES("properties", "text/plain"),

/**
* SQL */ SQL("sql", "application/sql"),

/**
* TIF */ TIF("tif", "image/tiff"),

/**
* TIFF */ TIFF("tiff", "image/tiff"),

/**
* SHP */ SHP("shp", "application/octet-stream"),

/**
* KML */ KML("kml", "application/vnd.google-earth.kml+xml"),

/**
* KMZ */ KMZ("kmz", "application/vnd.google-earth.kmz"),

/**
* LAS */ LAS("las", "application/octet-stream"),

/**
* PLY */ PLY("ply", "application/octet-stream"),

/**
* MD */ MD("md", "text/markdown");

/**
* 文件类型
*/
private final String code;

/**
* 文件ContentType类型
*/
private final String type;

public static ContentTypeEnum valueOfCode(String code) {
for (ContentTypeEnum typeEnum: ContentTypeEnum.values()) {
if (typeEnum.getCode().equalsIgnoreCase(code)) {
return typeEnum;
}
}
return null;
}
}