package com.lc.ibps.cloud.file.provider;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.jodconverter.OfficeDocumentConverter;
import org.jodconverter.office.DefaultOfficeManagerBuilder;
import org.jodconverter.office.OfficeException;
import org.jodconverter.office.OfficeManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
import com.artofsolving.jodconverter.DocumentConverter;
import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
import com.lc.ibps.api.base.constants.StateEnum;
import com.lc.ibps.api.base.constants.UserInfoConstants;
import com.lc.ibps.api.base.file.FileInfo;
import com.lc.ibps.base.core.constants.StringPool;
import com.lc.ibps.base.core.util.ArrayUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.FileUtil;
import com.lc.ibps.base.core.util.ZipUtil;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.framework.id.UniqueIdUtil;
import com.lc.ibps.base.framework.request.signature.annotation.Signature;
import com.lc.ibps.base.framework.validation.handler.HandlerValidationErrors;
import com.lc.ibps.base.framework.validation.handler.HandlerValidationUtil;
import com.lc.ibps.base.framework.validation.handler.IHandlerValidator;
import com.lc.ibps.base.framework.validation.handler.impl.UniqueHandlerValidation;
import com.lc.ibps.base.web.util.AppFileUtil;
import com.lc.ibps.base.web.util.RequestUtil;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.cloud.file.listener.PdfFileAlterationListenerAdaptor;
import com.lc.ibps.cloud.file.util.FileCleanUtil;
import com.lc.ibps.common.file.persistence.entity.AttachmentPo;
import com.lc.ibps.common.file.repository.AttachmentRepository;
import com.lc.ibps.components.upload.baidu.ueditor.ActionEnter;
import com.lc.ibps.components.upload.util.UploadUtil;
import com.lc.ibps.file.server.api.IDownloadService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
/**
* <pre>
*
* 构建组:ibps-comp-file-server
* 作者:eddy
* 邮箱:xuq@bpmhome.cn
* 日期:2018年5月22日-上午9:32:44
* 版权:广州流辰信息技术有限公司版权所有
* </pre>
*/
@Api(tags = "文件下载", value = "文件下载")
@Service
// @org.springframework.context.annotation.Lazy
public class DownloadProvider extends GenericUploadProvider implements IDownloadService {
private AtomicBoolean officeManagerInit = new AtomicBoolean(false);
private OfficeManager officeManager = null;
private static final String METHOD_TYPE_LOCAL = "local";
private static String MediaTypeAvg = "image/svg+xml";
@Value("${office.method:local}")
private String method;
@Value("${office.ip:127.0.0.1}")
private String ip;
@Value("${office.port:8100}")
private int port;
@Value("${office.home:/}")
private String home;
@Value("${office.ports:2000,2001,2002,2003,2004,2005,2006,2007,2008,2009}")
private String ports;
@Value("${office.max-tasks-per-process:256}")
private int maxProcess;
@Value("${office.lock:false}")
private boolean lock;
@Value("${spring.profiles.active}")
String env;
private AttachmentRepository attachmentRepository;
@Autowired
public void setAttachmentRepository(AttachmentRepository attachmentRepository) {
this.attachmentRepository = attachmentRepository;
}
@ApiOperation(value = "文件下载", notes = "文件下载")
@Override
public void download(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
FileInfo fileInfo = this.getUploadService().downloadFile(attachmentId);
if (BeanUtils.isNotEmpty(fileInfo)) {
byte[] fileBlob = fileInfo.getFileBytes();
String fileName = UploadUtil.getFileName(fileInfo.getFileName(), fileInfo.getExt());
RequestUtil.downLoadFileByByte(this.getRequest(), this.getResponse(), fileBlob, fileName);
}
} catch (Exception e) {
logger.error("/upload/download", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
@ApiOperation(value = "预览", notes = "对于文件的进行预览")
@Override
public void preview(
@ApiParam(name = "attachmentId", value = "附件id", required = true) @RequestParam(name = "attachmentId",
required = true) String attachmentId,
@ApiParam(name = "charset", value = "字符编码", required = false) @RequestParam(name = "charset",
required = false) String charset) {
OutputStream out = null;
InputStream is = null;
String[] image = {"jpg", "jpeg", "png", "gif"};
String[] video = {"mp3", "mp4", "MP3", "MP4"};
String[] office = {"doc", "docx", "ppt", "pptx", "xls", "xlsx"};
//添加 svg 矢量图类型,否则穿svg 前端无法显示
String[] svgImage = {"svg"};
IHandlerValidator<UniqueHandlerValidation> validator = null;
FileAlterationMonitor fileAlterationMonitor = null;
try {
AttachmentPo attachmentPo = attachmentRepository.get(attachmentId);
String ext = attachmentPo.getExt();
if ("pdf".equalsIgnoreCase(ext) || ArrayUtil.contains(office, ext)) {
getResponse().setContentType(MediaType.APPLICATION_PDF_VALUE);
} else if (ArrayUtil.contains(image, ext)) {
getResponse().setContentType(MediaType.IMAGE_PNG_VALUE);
} else if (ArrayUtil.contains(video, ext)) {
long len = attachmentPo.getTotalBytes();
String rangeString = getRequest().getHeader("Range");
long range =
Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
getResponse().setContentType("video/" + ext.toLowerCase());
getResponse().setHeader("content-disposition", "attachment;filename="
+ URLEncoder.encode(StringUtil.build(attachmentPo.getFileName(), ".", ext), "UTF-8"));
getResponse().setContentLengthLong(len);
getResponse().setHeader("Content-Range", String.valueOf(range + (len - 1)));
getResponse().setHeader("Accept-Ranges", "bytes");
// getResponse().setHeader("Etag", "W/9767057-1323779115364");//
// ContentType 添加 svg 矢量图类型,否则svg 传到前端无法显示
} else if (ArrayUtil.contains(svgImage, ext)) {
getResponse().setContentType(MediaTypeAvg);
} else {
getResponse().setContentType(MediaType.TEXT_HTML_VALUE);
}
if (ArrayUtil.contains(office, ext)) {
String path = FileCleanUtil.getOfficOutputDir();
String filePath = UploadUtil.mergeAbsolutePath(path, FileCleanUtil.FILE_RELATIVE_PATH);
String uid = UniqueIdUtil.getId();
String destFile = StringUtil.build(filePath, File.separator, attachmentId, ".pdf");
String destFileTimeout = StringUtil.build(filePath, File.separator, attachmentId, ".", uid,
FileCleanUtil.TIMEOUT_STR, "pdf");
String sourceFile = StringUtil.build(filePath, File.separator, attachmentId, ".", ext);
String sourceFileTimeout =
StringUtil.build(filePath, File.separator, attachmentId, ".", uid, FileCleanUtil.TIMEOUT_STR, ext);
validator = HandlerValidationUtil.createUniqueHandlerValidator2("attachment", "preview", null, null);
HandlerValidationErrors errors = validator.validate(attachmentId);
// 是否有人在预览并生成文件
if (null != errors && errors.hasError()) {
// 判断文件是否存在
if (!cn.hutool.core.io.FileUtil.exist(destFile)) {
String lock = new String("0");
File outputFile = new File(destFile);
fileAlterationMonitor = PdfFileAlterationListenerAdaptor.start(lock, outputFile);
// 阻塞线程,等待文件生成完成
synchronized (lock) {
logger.warn("file preview lock waiting.");
lock.wait(3000);
}
destFile = destFileTimeout;
office2pdf(attachmentId, destFile, sourceFile, sourceFileTimeout);
}
} else {
office2pdf(attachmentId, destFile, sourceFile, sourceFileTimeout);
}
byte[] readByte = FileUtil.readByte(destFile);
is = new ByteArrayInputStream(readByte);
} else {
FileInfo fileInfo = this.getUploadService().downloadFile(attachmentId);
is = new ByteArrayInputStream(fileInfo.getFileBytes());
}
HttpServletResponse response = getResponse();
if (StringUtil.isNotEmpty(charset)) {
response.setCharacterEncoding(charset);
}
out = response.getOutputStream();
byte[] bs = new byte[1024];
int n = 0;
while ((n = is.read(bs)) != -1) {
out.write(bs, 0, n);
}
out.flush();
} catch (Exception e) {
logger.error(e.getMessage(), e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
} finally {
PdfFileAlterationListenerAdaptor.stop(fileAlterationMonitor);
HandlerValidationUtil.processAfterInvoke(validator);
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private void office2pdf(String attachmentId, String destFile, String sourceFile, String sourceFileTimeout)
throws Exception {
IHandlerValidator<UniqueHandlerValidation> validator = null;
FileAlterationMonitor fileAlterationMonitor = null;
try {
validator = HandlerValidationUtil.createUniqueHandlerValidator2("attachment", "write.source", null, null);
HandlerValidationErrors errors = validator.validate(attachmentId);
// 是否有人在预览并生成文件
if (null != errors && errors.hasError()) {
if (!cn.hutool.core.io.FileUtil.exist(sourceFile)) {
String lock = new String("0");
File outputFile = new File(destFile);
fileAlterationMonitor = PdfFileAlterationListenerAdaptor.start(lock, outputFile);
// 阻塞线程,等待文件生成完成
synchronized (lock) {
logger.warn("file preview write source file lock waiting.");
lock.wait(3000);
}
sourceFile = sourceFileTimeout;
writeSourceFile(attachmentId, sourceFile);
}
} else {
writeSourceFile(attachmentId, sourceFile);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
PdfFileAlterationListenerAdaptor.stop(fileAlterationMonitor);
HandlerValidationUtil.processAfterInvoke(validator);
}
// 预览并发会出现异常,导致操作系统错误,带来一系列不可预估的问题,如:网卡重启、系统崩溃
if (!cn.hutool.core.io.FileUtil.exist(destFile)) {
office2PDF(sourceFile, destFile);
}
}
private void writeSourceFile(String attachmentId, String sourceFile) throws Exception {
if (!cn.hutool.core.io.FileUtil.exist(sourceFile)) {
FileUtil.createFolderFile(sourceFile);
FileInfo fileInfo = this.getUploadService().downloadFile(attachmentId);
FileUtil.writeByte(sourceFile, fileInfo.getFileBytes());
}
}
@ApiOperation(value = "删除文件", notes = "删除文件",
extensions = {@Extension(properties = {@ExtensionProperty(name = "submitCtrl", value = StringPool.Y)})})
@Signature
@Override
public APIResult<Void> delete(@ApiParam(name = "attachmentIds", value = "附件Id数组",
required = true) @RequestParam(name = "attachmentIds", required = true) String[] attachmentIds) {
APIResult<Void> result = new APIResult<Void>();
try {
this.getUploadService().deleteFile(attachmentIds);
result.setMessage("删除成功");
} catch (Exception e) {
setExceptionResult(result, StateEnum.ERROR_ATTACHMENT.getCode(), StateEnum.ERROR_ATTACHMENT.getText(), e);
}
return result;
}
@ApiOperation(value = "获取图片", notes = "对于图片的进行预览")
@Override
public void getImage(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
byte[] bytes = this.getUploadService().getFile(attachmentId);
if (bytes == null || bytes.length <= 0) {
bytes = "".getBytes();
}
this.getResponse().setContentType("image/jpeg; charset=UTF-8");
this.getResponse().getOutputStream().write(bytes);
} catch (Exception e) {
logger.error("/download/getImage", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
@ApiOperation(value = "获取文件", notes = "获取文件")
@Override
public void getFile(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
byte[] bytes = this.getUploadService().getFile(attachmentId);
if (bytes == null || bytes.length <= 0) {
bytes = "".getBytes();
}
this.getResponse().getOutputStream().write(bytes);
} catch (Exception e) {
logger.error("/download/getFile", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
@ApiOperation(value = "获取文件字节流", notes = "获取文件字节流")
@Override
public byte[] getFileByte(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
// 初始化上传Service
byte[] bytes = this.getUploadService().getFile(attachmentId);
if (bytes == null || bytes.length <= 0) {
bytes = "".getBytes();
}
return bytes;
} catch (Exception e) {
logger.error("/download/getFileByte", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
return null;
}
// 未经过调试
@ApiOperation(value = "附件下载", notes = "附件下载", hidden = true)
@Override
public void downloadByPath(
@ApiParam(name = "filePath", value = "附件保存路径", required = true) @RequestParam(name = "filePath",
required = true) String filePath,
@ApiParam(name = "fileName", value = "附件名称", required = true) @RequestParam(name = "fileName",
required = true) String fileName,
@ApiParam(name = "delete", value = "是否删除", required = false) @RequestParam(defaultValue = "false",
name = "delete", required = false) boolean delete) {
try {
String fullPath = StringUtil.build(StringUtil.trimSuffix(AppFileUtil.ATTACH_PATH, File.separator),
File.separator, filePath.replace("/", File.separator));
// 压缩文件
ZipUtil.zip(fullPath, delete);
// 下载文件
String zipFullName = StringUtil.build(fullPath, ".zip");
RequestUtil.downLoadFile(this.getRequest(), this.getResponse(), zipFullName,
StringUtil.build(fileName, ".zip"));
// 删除文件
if (delete) {
FileUtil.deleteFile(zipFullName);
}
} catch (Exception e) {
logger.error("/download/download", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
// 未经过调试
@ApiOperation(value = "获取头像", notes = "获取头像", hidden = true)
@Override
public void getAvatar(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
byte[] fileBlob = this.getUploadService().getFile(attachmentId);
this.getResponse().getOutputStream().write(fileBlob);
} catch (Exception e) {
logger.error("/attachment/getAvatar", e);
// 出错了输出默认的
String fullPath = AppFileUtil.getRealPath(UserInfoConstants.DEFAULT_USER_IMAGE);
try {
byte[] bytes = FileUtil.readByte(fullPath);
this.getResponse().getOutputStream().write(bytes);
} catch (Exception e2) {
logger.error("/download/getAvatar", e2);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
}
// 未经过调试
@ApiOperation(value = " 获取office控件", notes = "获取office控件", hidden = true)
@Override
public void office(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
String path = FileCleanUtil.getOfficOutputDir();
FileInfo fileInfo = this.getUploadService().downloadFile(attachmentId);
if (BeanUtils.isNotEmpty(fileInfo)) {
String ext = fileInfo.getExt();
String[] office = {"doc", "docx", "ppt", "pptx", "xls", "xlsx"};
String filePath = UploadUtil.mergeAbsolutePath(path, FileCleanUtil.FILE_RELATIVE_PATH);
String destFile = StringUtil.build(filePath, File.separator, attachmentId, ".pdf");
if (ArrayUtil.contains(office, ext)) {
String sourceFile = StringUtil.build(filePath, File.separator, attachmentId, ".", ext);
if (!FileUtil.isExistFile(sourceFile)) {
FileUtil.createFolderFile(sourceFile);
FileUtil.writeByte(sourceFile, fileInfo.getFileBytes());
}
if (!FileUtil.isExistFile(destFile)) {
office2PDF(sourceFile, destFile);
}
} else {
if (StringUtil.isNotEmpty(ext) && "pdf".equalsIgnoreCase(ext)) {
// 直接是pdf的写入
if (!FileUtil.isExistFile(destFile)) {
FileUtil.createFolderFile(destFile);
FileUtil.writeByte(destFile, fileInfo.getFileBytes());
}
}
}
}
} catch (Exception e) {
logger.error("/download/office", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
// 未经过调试
@ApiOperation(value = " pdf 输入", notes = "pdf 输入", hidden = true)
@Override
public void pdf(@ApiParam(name = "attachmentId", value = "附件id",
required = true) @RequestParam(name = "attachmentId", required = true) String attachmentId) {
try {
String path = FileCleanUtil.getOfficOutputDir();
String filePath = UploadUtil.mergeAbsolutePath(path, FileCleanUtil.FILE_RELATIVE_PATH);
String destFile = StringUtil.build(filePath, File.separator, attachmentId, ".pdf");
RequestUtil.downLoadFile(this.getRequest(), this.getResponse(), destFile, attachmentId);
} catch (Exception e) {
logger.error("/download/pdf", e);
try {
RequestUtil.responseNotExsitsFile(getResponse());
} catch (IOException e1) {
}
}
}
/**
* 将Office文档转换为PDF. 运行该函数需要用到OpenOffice, OpenOffice下载地址为 http://www.openoffice.org/
*
* <pre>
*
* 方法示例:
* String sourcePath = "F:\\office\\source.doc";
* String destFile = "F:\\pdf\\dest.pdf";
* Converter.office2PDF(sourcePath, destFile);
* </pre>
*
* @param sourceFile 源文件, 绝对路径. 可以是Office2003-2007全部格式的文档, Office2010的没测试. 包括.doc, .docx, .xls, .xlsx, .ppt, .pptx等.
* 示例: F:\\office\\source.doc
* @param destFile 目标文件. 绝对路径. 示例: F:\\pdf\\dest.pdf
* @return 操作成功与否的提示信息. 如果返回 -1, 表示找不到源文件, 或url.properties配置错误; 如果返回 0, 则表示操作成功; 返回1, 则表示转换失败
*/
private int office2PDF(String sourceFile, String destFile) {
return singleManager(sourceFile, destFile);
}
@PostConstruct
private void getOrCreateOfficeManager() {
//dev本地环境暂时直接返回,这样不用搭建环境open office
if("dev".equals(env)) {
return;
}
if (METHOD_TYPE_LOCAL.equals(method)) {
String officeHome = getOfficeHome();
DefaultOfficeManagerBuilder config = new DefaultOfficeManagerBuilder();
config.setOfficeHome(officeHome);
config.setPortNumbers(readPortNumbers());
config.setMaxTasksPerProcess(maxProcess);
boolean succ = officeManagerInit.compareAndSet(false, true);
if (succ && officeManager == null) {
try {
officeManager = config.build();
if (!officeManager.isRunning()) {
officeManager.start();
}
} catch (OfficeException e) {
logger.error("officeManager start:", e);
}
}
try {
if (!officeManager.isRunning()) {
officeManager.start();
}
} catch (OfficeException e) {
logger.error("officeManager start:", e);
}
}
}
private int[] readPortNumbers() {
String portNumbers = ports;
String[] portNumbersArray = portNumbers.split(StringPool.COMMA);
int[] portNumbersIntArray = new int[portNumbersArray.length];
for (int i = 0, sz = portNumbersArray.length; i < sz; i++) {
String portNumber = portNumbersArray[i];
portNumbersIntArray[i] = Integer.valueOf(portNumber);
}
return portNumbersIntArray;
}
private int singleManager(String sourceFile, String destFile) {
try {
File inputFile = new File(sourceFile);
// 如果目标路径不存在, 则新建该路径
File outputFile = new File(destFile);
if (!outputFile.getParentFile().exists()) {
outputFile.getParentFile().mkdirs();
}
if (METHOD_TYPE_LOCAL.equals(method)) {
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
converter.convert(inputFile, outputFile);
} else {
// 创建连接
OpenOfficeConnection connection = new SocketOpenOfficeConnection(ip, port);
// 远程连接OpenOffice服务
connection.connect();
// 创建文件转换器
DocumentConverter converter = new StreamOpenOfficeDocumentConverter(connection);
converter.convert(inputFile, outputFile);
}
return 0;
} catch (Exception e) {
logger.error("/download/office :", e);
} finally {
}
return 1;
}
private String getOfficeHome() {
String OFFICE_HOME = home;// 这里是OpenOffice的安装目录
// 如果从文件中读取的URL地址最后一个字符不是 '\',则添加'\'
if (OFFICE_HOME.charAt(OFFICE_HOME.length() - 1) != File.separatorChar) {
OFFICE_HOME = StringUtil.build(OFFICE_HOME, File.separatorChar);
}
return OFFICE_HOME;
}
@ApiOperation(value = "ueditor请求", notes = "ueditor请求")
@Override
public String ueditor(HttpServletRequest request) {
try {
String rootPath = request.getSession().getServletContext().getRealPath("/");
return new ActionEnter(request, rootPath).exec();
} catch (Exception e) {
logger.error("/ueditor/action", e);
}
return "";
}
@ApiOperation(value = "ueditor请求", notes = "ueditor请求")
@Override
public String ueditorAction(HttpServletRequest request) {
try {
String rootPath = request.getSession().getServletContext().getRealPath("/");
return new ActionEnter(request, rootPath).exec();
} catch (Exception e) {
logger.error("/ueditor/action", e);
}
return "";
}
}
这个是ftp工具类
最新发布