ny
昨天 b6f169fe43a2b13f351aefc152374fc7f0bc8cb7
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
package jnpf.service.impl;
 
import cn.hutool.core.util.URLUtil;
import jakarta.servlet.http.HttpServletResponse;
import jnpf.base.UserInfo;
import jnpf.config.ConfigValueUtil;
import jnpf.constant.FileTypeConstant;
import jnpf.constant.GlobalConst;
import jnpf.constant.MsgCode;
import jnpf.entity.FileParameter;
import jnpf.exception.DataException;
import jnpf.model.*;
import jnpf.service.FileService;
import jnpf.util.*;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.dromara.x.file.storage.core.FileInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import org.springframework.web.multipart.MultipartFile;
 
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
 
 
@Slf4j
@Service
public class FileServiceImpl implements FileService {
 
    private List<String> whiteImageFolder = Arrays.asList(FileTypeConstant.USERAVATAR.toLowerCase(), FileTypeConstant.BIVISUALPATH.toLowerCase());
 
    @Autowired
    private ConfigValueUtil configValueUtil;
//    @Autowired
//    private YozoUtils yozoUtils;
 
    @Override
    public String getPath(String type) {
        return FilePathUtil.getFilePath(type);
    }
 
    @Override
    public String getLocalBasePath() {
        return FileUploadUtils.getLocalBasePath();
    }
 
    @Override
    public UploaderVO uploadFile(MergeChunkDto mergeChunkDto, MultipartFile file) {
        String fileType = UpUtil.getFileType(file);
        if (StringUtil.isEmpty(fileType)) {
            fileType = mergeChunkDto.getFileType();
        }
        //验证类型
        if (!OptimizeUtil.fileType(configValueUtil.getAllowUploadFileType(), fileType)) {
            throw new DataException(MsgCode.FA017.get());
        }
        PathTypeModel pathTypeModel = new PathTypeModel();
        pathTypeModel.setPathType(mergeChunkDto.getPathType());
        pathTypeModel.setTimeFormat(mergeChunkDto.getTimeFormat());
        pathTypeModel.setSortRule(mergeChunkDto.getSortRule());
        pathTypeModel.setFolder(mergeChunkDto.getFolder());
//        String orgFileName = file.getOriginalFilename();
//        if (OptimizeUtil.fileSize(file.getSize(), 1024000)) {
//            return ActionResult.fail("上传失败,文件大小超过1M");
//        }
//        if ("mail".equals(type)) {
//            type = "temporary";
//        }
        if ("selfPath".equals(pathTypeModel.getPathType())) {
            if (StringUtil.isNotEmpty(pathTypeModel.getFolder())) {
                String folder = pathTypeModel.getFolder();
                folder = folder.replaceAll("\\\\", "/");
//                String regex = "^[a-z0-9A-Z\\u4e00-\\u9fa5\\\\\\/]+$";
                //文件夹名以字母或数字开头,由字母、数字、下划线和连字符组成,长度不超过100个字符
                String regex = "^[a-zA-Z0-9][a-zA-Z0-9_\\-\\\\\\/]{0,99}$";
                if (!folder.matches(regex)) {
                    throw new DataException(MsgCode.FA038.get());
                }
            }
        }
        //实际文件名
        String fileName = DateUtil.dateNow("yyyyMMdd") + "_" + RandomUtil.uuId() + "." + fileType;
        //文件上传路径
//        String filePath = FilePathUtil.getFilePath(type.toLowerCase());
        String type = mergeChunkDto.getType();
 
        //文件自定义路径相对路径
        String relativeFilePath = "";
        if (pathTypeModel != null && "selfPath".equals(pathTypeModel.getPathType()) && pathTypeModel.getSortRule() != null) {
            // 按路径规则顺序构建生成目录
            String sortRule = pathTypeModel.getSortRule();
            List<String> rules = null;
            if (sortRule.contains("[")) {
                rules = JsonUtil.getJsonToList(sortRule, String.class);
            } else {
                rules = Arrays.asList(pathTypeModel.getSortRule().split(","));
            }
            for (String rule : rules) {
                // 按用户存储
                if ("1".equals(rule)) {
                    UserInfo userInfo = UserProvider.getUser();
                    relativeFilePath += userInfo.getUserAccount() + "/";
                }
                // 按照时间格式
                else if (StringUtil.isNotEmpty(pathTypeModel.getTimeFormat()) && "2".equals(rule)) {
                    String timeFormat = pathTypeModel.getTimeFormat();
                    timeFormat = timeFormat.replaceAll("YYYY", "yyyy");
                    timeFormat = timeFormat.replaceAll("DD", "dd");
                    LocalDate currentDate = LocalDate.now();
                    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(timeFormat);
                    String currentDateStr = currentDate.format(formatter);
                    relativeFilePath += currentDateStr;
                    if (!currentDateStr.endsWith("/")) {
                        relativeFilePath += "/";
                    }
                }
                // 按自定义目录
                else if (StringUtil.isNotEmpty(pathTypeModel.getFolder()) && "3".equals(rule)) {
                    String folder = pathTypeModel.getFolder();
                    folder = folder.replaceAll("\\\\", "/");
                    relativeFilePath += folder;
                    if (!folder.endsWith("/")) {
                        relativeFilePath += "/";
                    }
                }
            }
 
            if (StringUtil.isNotEmpty(relativeFilePath)) {
                relativeFilePath = StringUtil.replaceMoreStrToOneStr(relativeFilePath, "/");
                if (relativeFilePath.startsWith("/")) {
                    relativeFilePath = relativeFilePath.substring(1);
                }
                //filePath += relativeFilePath;
                fileName = relativeFilePath.replaceAll("/", ",") + fileName;
            }
        }
 
 
        UploaderVO vo = UploaderVO.builder().fileSize(file.getSize()).fileExtension(fileType).build();
//        //上传文件
//        if ("im".equalsIgnoreCase(type)){
//            type = "imfile";
//        }
        FileInfo fileInfo = FileUploadUtils.uploadFile(new FileParameter(type, fileName).setThumbnail(true), file);
        fileName = fileInfo.getFilename();
        String thFilename = fileInfo.getThFilename();
        if (!StringUtil.isNotEmpty(thFilename)) {
            //小图没有压缩直接用原图
            thFilename = fileName;
        }
        //自定义文件实际文件名
        if (StringUtil.isNotEmpty(relativeFilePath)) {
            fileName = relativeFilePath.replaceAll("/", ",") + fileName;
            thFilename = relativeFilePath.replaceAll("/", ",") + thFilename;
        }
        vo.setName(fileName);
 
        vo.setUrl(UploaderUtil.uploaderImg("/api/file/Image/" + type + "/", fileName));
        vo.setThumbUrl(UploaderUtil.uploaderImg("/api/file/Image/" + type + "/", thFilename));
 
        //上传到永中
        if ("yozo".equals(configValueUtil.getPreviewType())) {
//            try {
//                @Cleanup InputStream inputStream = file.getInputStream();
//                String s = yozoUtils.uploadFileInPreview(inputStream, orgFileName);
//                Map<String, Object> map = JsonUtil.stringToMap(s);
//                if ("操作成功".equals(map.get("message"))) {
//                    Map<String, Object> dataMap = JsonUtil.stringToMap(String.valueOf(map.get("data")));
//                    String verId = String.valueOf(dataMap.get("fileVersionId"));
//                    vo.setFileVersionId(verId);
//                }
//            } catch (Exception e) {
//                System.out.println("上传到永中失败");
//                e.printStackTrace();
//            }
        }
        return vo;
    }
 
    @Override
    public ChunkRes checkChunk(Chunk chunk) {
        String type = chunk.getExtension();
        if (!OptimizeUtil.fileType(configValueUtil.getAllowUploadFileType(), type)) {
            throw new DataException(MsgCode.FA017.get());
        }
        String identifier = chunk.getIdentifier();
        String path = getPath(FileTypeConstant.TEMPORARY);
        String filePath = XSSEscape.escapePath(path + identifier);
        List<File> chunkFiles = FileUtil.getFile(new File(FileUploadUtils.getLocalBasePath() + filePath));
        List<Integer> existsChunk = chunkFiles.stream().filter(f -> {
            if (f.getName().endsWith(".tmp")) {
                FileUtils.deleteQuietly(f);
                return false;
            } else {
                return f.getName().startsWith(identifier);
            }
        }).map(f -> Integer.parseInt(f.getName().replace(chunk.getIdentifier().concat("-"), ""))).collect(Collectors.toList());
        ChunkRes chunkRes = ChunkRes.builder().merge(chunk.getTotalChunks().equals(existsChunk.size())).chunkNumbers(existsChunk).build();
        return chunkRes;
    }
 
    @Override
    public ChunkRes uploadChunk(Chunk chunk, MultipartFile file) {
        String type = chunk.getExtension();
        if (!OptimizeUtil.fileType(configValueUtil.getAllowUploadFileType(), type)) {
            throw new DataException(MsgCode.FA017.get());
        }
        ChunkRes chunkRes = ChunkRes.builder().build();
        chunkRes.setMerge(false);
        File chunkFile = null;
        File chunkTmpFile = null;
        try {
            String filePath = FileUploadUtils.getLocalBasePath() + getPath(FileTypeConstant.TEMPORARY);
            Integer chunkNumber = chunk.getChunkNumber();
            String identifier = XSSEscape.escapePath(chunk.getIdentifier());
            String chunkTempPath = XSSEscape.escapePath(filePath + identifier);
            File path = new File(chunkTempPath);
            if (!path.exists()) {
                path.mkdirs();
            }
            String chunkName = XSSEscape.escapePath(identifier.concat("-") + chunkNumber);
            String chunkTmpName = XSSEscape.escapePath(chunkName.concat(".tmp"));
            chunkFile = new File(chunkTempPath, chunkName);
            chunkTmpFile = new File(chunkTempPath, chunkTmpName);
            if (chunkFile.exists() && chunkFile.length() == chunk.getCurrentChunkSize()) {
                System.out.println("该分块已经上传:" + chunkFile.getName());
            } else {
                @Cleanup InputStream inputStream = file.getInputStream();
                FileUtils.copyInputStreamToFile(inputStream, chunkTmpFile);
                chunkTmpFile.renameTo(chunkFile);
            }
            int existsSize = (int) FileUtil.getFile(new File(chunkTempPath)).stream().filter(f ->
                    f.getName().startsWith(identifier) && !f.getName().endsWith(".tmp")
            ).count();
            chunkRes.setMerge(Objects.equals(existsSize, chunk.getTotalChunks()));
        } catch (Exception e) {
            try {
                FileUtils.deleteQuietly(chunkTmpFile);
                FileUtils.deleteQuietly(chunkFile);
            } catch (Exception ee) {
                e.printStackTrace();
            }
            System.out.println("上传异常:" + e);
            throw new DataException(MsgCode.FA033.get());
        }
        return chunkRes;
    }
 
    @Override
    public UploaderVO mergeChunk(MergeChunkDto mergeChunkDto) {
        String identifier = XSSEscape.escapePath(mergeChunkDto.getIdentifier());
        String path = FileUploadUtils.getLocalBasePath() + getPath(FileTypeConstant.TEMPORARY);
        String filePath = XSSEscape.escapePath(path + identifier);
        String uuid = RandomUtil.uuId();
        String partFile = XSSEscape.escapePath(path + uuid + "." + mergeChunkDto.getExtension());
        UploaderVO vo = UploaderVO.builder().build();
        try {
            List<File> mergeFileList = FileUtil.getFile(new File(filePath));
            @Cleanup FileOutputStream destTempfos = new FileOutputStream(partFile, true);
            for (int i = 0; i < mergeFileList.size(); i++) {
                String chunkName = identifier.concat("-") + (i + 1);
                File files = new File(filePath, chunkName);
                if (files.exists()) {
                    FileUtils.copyFile(files, destTempfos);
                }
            }
            File partFiles = new File(partFile);
            if (partFiles.exists()) {
                MultipartFile multipartFile = FileUtil.createFileItem(partFiles);
                vo = uploadFile(mergeChunkDto, multipartFile);
                FileUtil.deleteTmp(multipartFile);
            }
        } catch (Exception e) {
            log.error("合并分片失败: {}", e.getMessage());
            throw new DataException(MsgCode.FA033.get());
        } finally {
            FileUtils.deleteQuietly(new File(filePath));
            FileUtils.deleteQuietly(new File(partFile));
        }
        return vo;
    }
 
    @Override
    public void downloadFile(String encryption, String downName) {
        String fileNameAll = DesUtil.aesDecode(encryption);
        if (!StringUtil.isEmpty(fileNameAll)) {
            fileNameAll = fileNameAll.replaceAll("\n", "");
            String[] data = fileNameAll.split("#");
            String cacheKEY = data.length > 0 ? data[0] : "";
            String fileName = XSSEscape.escapePath(data.length > 1 ? data[1] : "");
            String type = data.length > 2 ? data[2] : "";
            Object ticketObj = TicketUtil.parseTicket(cacheKEY);
            //下载文件
//            String typePath = FilePathUtil.getFilePath(type.toLowerCase());
//            if (fileName.indexOf(",") >= 0) {
//                typePath += fileName.substring(0, fileName.lastIndexOf(",") + 1).replaceAll(",", "/");
//                fileName = fileName.substring(fileName.lastIndexOf(",") + 1);
//            }
            fileName = URLUtil.decode(fileName, GlobalConst.DEFAULT_CHARSET);
            FileParameter fileParameter = new FileParameter(type, fileName);
            //验证缓存
            if (ticketObj != null) {
                boolean nodelete = false;
                //某些手机浏览器下载后会有提示窗口, 会访问两次、三次下载地址,请求头不是app类型
                TicketUtil.updateTicket(cacheKEY, "1", 10L);
                FileUploadUtils.downloadFile(fileParameter, inputStream -> {
                    FileDownloadUtil.outFile(inputStream, downName);
                });
                if (FileTypeConstant.FILEZIPDOWNTEMPPATH.equals(type) && !nodelete) { //删除打包的临时文件,释放存储
                    FileUploadUtils.deleteFileByPathAndFileName(fileParameter);
                }
            } else {
                if (FileTypeConstant.FILEZIPDOWNTEMPPATH.equals(type)) { //删除打包的临时文件,释放存储
                    FileUploadUtils.deleteFileByPathAndFileName(fileParameter);
                }
                throw new DataException(MsgCode.FA039.get());
            }
        }
    }
 
    @Override
    public boolean fileExists(String path, String fileName) {
        return FileUploadUtils.exists(new FileParameter(path, fileName));
    }
 
    @Override
    public String previewFile(PreviewParams previewParams) {
        //读取允许文件预览类型
        String allowPreviewType = configValueUtil.getAllowPreviewFileType();
        String[] fileType = allowPreviewType.split(",");
 
        String fileName = XSSEscape.escape(previewParams.getFileName());
 
        //文件预览类型检验
        String docType = fileName.substring(fileName.lastIndexOf(".") + 1);
        String s = Arrays.asList(fileType).stream().filter(type -> type.equals(docType)).findFirst().orElse(null);
 
        if (StringUtil.isEmpty(s)) {
            throw new DataException(MsgCode.FA040.get());
        }
 
        //解析文件url 获取类型
        String type = null;
 
        String fileNameAll = previewParams.getFileDownloadUrl();
        if (!StringUtil.isEmpty(fileNameAll)) {
            String[] data = fileNameAll.split("/");
            if (data.length > 4) {
                type = data[4];
            } else {
                type = "";
            }
 
        }
//        type = getPath(FileTypeConstant.ANNEXPIC);
        String url;
        //文件预览策略
        if ("yozo".equals(configValueUtil.getPreviewType())) {
//            if (StringUtil.isEmpty(previewParams.getFileVersionId())) {
//                throw new DataException(MsgCode.FA041.get());
//            }
//
//            String fileVersionId = XSSEscape.escape(previewParams.getFileVersionId());
//
//            //获取签名
//            Map<String, String[]> parameter = new HashMap<String, String[]>();
//            parameter.put("appId", new String[]{YozoParams.APP_ID});
//            parameter.put("fileVersionId", new String[]{fileVersionId});
//            String sign = yozoUtils.generateSign(YozoParams.APP_ID, YozoParams.APP_KEY, parameter).getData();
//            url = "http://eic.yozocloud.cn/api/view/file?fileVersionId="
//                    + fileVersionId
//                    + "&appId="
//                    + YozoParams.APP_ID
//                    + "&sign="
//                    + sign;
            url = "";
        } else {
//            String[] split = fileNameAll.split("/");
//            if (split.length > 5) {
//                type = FilePathUtil.getFilePath(type);
//                String fName = split[5];
//                if (fName.contains(",")) {
//                    fName = fName.replaceAll(",", "/");
//                    type += fName.substring(0, fName.lastIndexOf("/") + 1);
//                    fileName = fName.substring(fName.lastIndexOf("/") + 1);
//                }
//            }
//            url = configValueUtil.getApiDomain() + UploaderUtil.uploaderFile(fileName + "#" + type) + "&name=" + fileName + "&fullfilename=" + fileName;
            String downFileName = fileName;
            if (downFileName.contains(",")) {
                downFileName = downFileName.substring(downFileName.lastIndexOf(",") + 1);
            }
            url = configValueUtil.getApiDomain() + "/api/file/Image/" + type + "/" + fileName + "?fullfilename=" + downFileName + "&s=" + UserProvider.getUser().getSecurityKey();// + "&name=" + fileName + "&fullfilename=" + fileName;
            //encode编码
            String fileUrl = Base64.encodeBase64String(url.getBytes());
            url = configValueUtil.getKkFileUrl() + "onlinePreview?url=" + fileUrl;
        }
        return url;
    }
 
    @Override
    public void flushFile(String type, String fileName, String securityKey, boolean redirect) {
        //页面播放视频的情况下取消重定向
        boolean isPlayVideo = StringUtil.isNotEmpty(ServletUtil.getHeader(HttpHeaders.RANGE));
        //目录校验, 开放UserAvatar、BiVisualPath
        if (!whiteImageFolder.contains(type.toLowerCase())) {
            if (StringUtil.isEmpty(securityKey)) {
                throw new DataException(MsgCode.FA039.get());
            }
            String ticket = DesUtil.aesOrDecode(securityKey, false, true);
            String token = TicketUtil.parseTicket(ticket);
            if (token == null) {
                throw new DataException(MsgCode.FA039.get());
            }
            UserInfo user = UserProvider.getUser(token);
            if (user.getUserId() == null) {
                TicketUtil.deleteTicket(ticket);
                throw new DataException(MsgCode.FA039.get());
            }
        }
        if (!isPlayVideo && StringUtil.isNotEmpty(securityKey) && redirect) {
            String downName = fileName;
            if (downName.contains(",")) {
                downName = downName.substring(downName.lastIndexOf(",") + 1);
            }
            String urlEncodeFileName = URLUtil.encode(fileName, GlobalConst.DEFAULT_CHARSET);
            String urlEncodeDownName = URLUtil.encode(downName, GlobalConst.DEFAULT_CHARSET);
            String url = configValueUtil.getApiDomain() + UploaderUtil.uploaderFile(urlEncodeFileName + "#" + type) + "&name=" + urlEncodeDownName + "&fullfilename=" + urlEncodeDownName;
            try {
                ServletUtil.getResponse().sendRedirect(url);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } else {
            FileUploadUtils.downloadFile(new FileParameter(type, fileName), inputStream -> {
                if (isPlayVideo) {
                    FileInfo remoteFileInfo = FileUploadUtils.getRemoteFileInfo(new FileParameter(type, fileName));
                    streamVideo(inputStream, remoteFileInfo.getFilename(), remoteFileInfo.getSize());
                } else {
                    FileDownloadUtil.flushFile(inputStream, fileName);
                }
            });
        }
    }
 
    /**
     * 视频断点续传方法
     *
     * @param input
     * @param fileName
     * @param length
     */
    public void streamVideo(InputStream input, String fileName, long length) {
        HttpServletResponse response = ServletUtil.getResponse();
        String rangeHeader = ServletUtil.getHeader(HttpHeaders.RANGE);
        long fileSize = length;
        final long CHUNK_SIZE = 1024 * 1024 * 1; // 1MB
        String range = rangeHeader.replace("bytes=", "");
        String[] ranges = range.split("-");
 
        long start = Long.parseLong(ranges[0]);
        long end;
 
        if (ranges.length > 1 && !ranges[1].isEmpty()) {
            // 客户端明确指定了结束位置:bytes=start-end
            end = Long.parseLong(ranges[1]);
        } else {
            // 客户端只指定了开始位置:bytes=start-
            end = start + CHUNK_SIZE - 1;
        }
        // 确保不超出文件边界
        end = Math.min(end, fileSize - 1);
 
        // 边界检查
        if (start >= fileSize || end < start) {
            response.setStatus(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE.value());
            response.setHeader("Content-Range", "bytes */" + fileSize);
            return;
        }
        long contentLength = end - start + 1;
 
        if (fileName == null) {
            fileName = ".mp4";
        }
        // 设置响应头
        response.setStatus(HttpStatus.PARTIAL_CONTENT.value());
        response.setContentType(MediaTypeFactory.getMediaType(fileName).orElse(MediaType.ALL).toString());
        response.setHeader("Content-Length", String.valueOf(contentLength));
        response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileSize);
        response.setHeader("Accept-Ranges", "bytes");
 
        try {
            // 注意:end + 1 是因为copyRange的结束位置是不包含的
            StreamUtils.copyRange(input, response.getOutputStream(), start, end + 1);
        } catch (Exception e) {
        }
    }
}