本帖内容:文件上传,下载,在线预览
文件在线预览是使用PDF.js插件实现的,通过在后台获取文件流返回给前台来实现文件的在线预览。
springboot项目
目录结构:
前台HTML代码:
前台样式就不放了,自己调节,引入jquery.js
<section class="container">
<div class="append">
<p class="agr_p">
<label>合同上传:</label>
<input type="file" multiple="multiple" name="fileName" id="file" value="浏览..." style="float: left;padding-left: 10px;"/>
<input type="submit" value="上传" style="display:none;" />
</p>
<p class="agr_p" id="files">
<!--<lable value="" padding-left="1000px">agreement_8.txt<a>删除</a></lable><br/>-->
</p>
<p class="agr_p">
<label></label>
<a class="add_button " onclick="addAgreement()"> 创建</a>
</p>
<p class="agr_p">
<label></label>
<a class="add_button " onclick="downfile()"> 下载</a>
</p>
<p class="agr_p">
<label></label>
<a class="add_button " onclick="findFile()"> 预览</a>
</p>
</div>
</section>
js代码:
var arr=[];
$(function(){
//文件上传的列表展示
$("#file").change(function () {
var a=arr.length;
var size=$("#file")[0].files;
//将对象转化为数组
for(var i=0,len=size.length;i<len;i++){
arr[a+i]=size[i];
}
$("#files").html();
for(var i=0;i<size.length;i++){
$("#files").append("<div class='aaa"+(a+i)+"' style='height: 34px;line-height: 34px;padding-left: 150px;'><span style='width:300px;float: left;'>"+size[i].name+"</span><a class='dela' onclick='removeFile("+(a+i)+")'>删除</a></div>");
}
});
});
//预览文件
function findFile(){
sessionStorage.setItem("names","123");//其他参数
var dat=encodeURIComponent("/fileTest/findFile?newName=1547616634746.pdf&url=opt/test/");//文件名,文件相对路径
var urls="/findFile/web/findAgreement.html?file="+dat;
window.location.href=urls;
}
//下载文件
function downfile(){
window.location.href="/fileTest/downFile?fileName=123456.pdf&newName=1547616634746.pdf&url=opt/test/";
}
/*
* 文件上传
* */
function addAgreement(){
var formData = new FormData();
formData.append("age","18");
formData.append("names","天选");
//这是另外一种封装文件为参数的方法
// var size=$("#file")[0].files;
// for(var i=0;i<size.length;i++){
// var name=size[i].name;
// var str=name.substring(name.length-3);
// if(str!="doc"&&str!="docx"&&str!="pdf"){
// alert("不可以有非doc,docx,pdf文档");
// continue;
// }
// //这里是放置文件
// formData.append("file",size[i]);
// }
for(var i=0;i<arr.length;i++){
var name=arr[i].name;
var index=name.lastIndexOf(".");
var str=name.substring(index+1);
if(str!="doc"&&str!="docx"&&str!="pdf"){
alert("不可以有非doc,docx,pdf文档");
continue;
}
//这里是放置文件
formData.append("file",arr[i]);
}
$.ajax({
url: "/fileTest/uploadFile",
type: "post",
data:formData,
contentType:false,
processData:false,
success: function(data){
alert("返回结果为:"+data);
}
});
}
//文件删除
function removeFile(i) {
$(".aaa"+i).hide();
arr.splice(i, 1);//删除某个元素
}
后台controller代码为:
import com.qtong.afin.core.util.ConfigProperties;
import com.qtong.afin.core.util.ftp.Doc2Html;
import com.qtong.afin.core.util.ftp.FtpHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/fileTest")
public class FileTestController {
/**
* 日志
*/
public static Logger logger = LoggerFactory.getLogger(FileTestController.class);
@Autowired
ConfigProperties configProperties;
/**
* 文件在线预览`
*/
@RequestMapping(value = "/findFile")
@ResponseBody
public void findContract(String newName, String url,HttpServletRequest request, HttpServletResponse response){
//h:/ftp_upload/ opt/test/ *.doc
String path1=configProperties.getFtpDownPath()+url+newName;
//h:/ftp_upload/ opt/test/
String path2=configProperties.getFtpDownPath()+configProperties.getFtpPath();
String filePri=newName.substring(newName.lastIndexOf(".")+1);//文件后缀名
String fileName=newName.substring(0,newName.lastIndexOf("."));//文件名
if("pdf".equals(filePri)){//查看是否是PDF文件
File file=new File(path1);
if (file.exists()){
byte[] data = null;
try {
FileInputStream input = new FileInputStream(file);
data = new byte[input.available()];
input.read(data);
response.getOutputStream().write(data);
input.close();
} catch (Exception e) {
logger.info("pdf处理文件异常"+e);
}
}else{
return;
}
}else {//非PDF文件
File file=new File(path2+fileName+".pdf");
if(!file.exists()){//查看之前是否转过PDF文件,转过则就可能存在,否则则就转PDF文件,转PDF文件使用软件是openoffice(应该是这个名)
//转成PDF文件
file = Doc2Html.uploadFile(path2, path1, "agreementfilepdf");
}
//返回文件流
if (file.exists()){
byte[] data = null;
try {
FileInputStream input = new FileInputStream(file);
data = new byte[input.available()];
input.read(data);
response.getOutputStream().write(data);
input.close();
} catch (Exception e) {
logger.info("pdf处理文件异常"+e);
}
}else{
return;
}
}
}
/**
* 合同文件下载,非ftp下载
*/
@RequestMapping(value = "/downFile")
@ResponseBody
public void download(String fileName,String newName,String url,HttpServletRequest request,HttpServletResponse response) {
try {
String path =configProperties.getFtpDownPath()+ url+newName;//文件所在地址,newName是实际存放的文件名
// 读到流中
InputStream inStream = new FileInputStream(path);//文件的存放路径
// 设置输出的格式
response.reset();
response.setContentType("bin");
response.addHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");//这里的文件名是指客户端下载后保存文件的文件名
// 循环取出流中的数据
byte[] b = new byte[100];
int len;
try {
while ((len = inStream.read(b)) > 0) response.getOutputStream().write(b, 0, len);
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 文件上传
* @param request
* @param response
* @return
*/
@RequestMapping(value = "/uploadFile")
@ResponseBody
public String addAgreement2(@RequestParam(value = "age", required = true)String age,
String names,
HttpServletRequest request,
HttpServletResponse response) {
logger.info("接收到的参数为:age="+age+"names="+names);//传的其他参数
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");//获取前台传过来的文件集
for (MultipartFile file : files) {
if (files.isEmpty()) {//判断文件是否非空
continue;
}
//文件上传操作
//文件名
//获取文件名字 文件原名 文件新名newName
String oldNames = file.getOriginalFilename();//获取文件名字
int i = oldNames.lastIndexOf(".");
String substring = oldNames.substring(i);//截取文件后缀名
Long l = System.currentTimeMillis();
String fileName2 = l.toString();
String newName = fileName2 + substring;//形成新的文件名
//上传路径
String path = configProperties.getFtpPath();
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
//执行文件上传操作
FtpHelper.uploadFile(configProperties.getFtpUrl(), Integer.valueOf(configProperties.getFtpPort()), configProperties.getFtpUsername(), configProperties.getFtpPassword(), path, newName, inputStream);
Map<String, Object> map = new HashMap<>();
map.put("oldName", oldNames);//文件原来的名字
map.put("newName", newName);//文件的新名字
map.put("path", path);
logger.info(map.toString());
}
//根据结果返回结果集
return "success";
}
}
pdf.js工具类接收其他参数的代码:至于文件流,在跳转页面的时候由PDF.js直接发起请求并获取流了,基本无需操心,反正我也不知道它怎么请求的,有心人可以自己找找。
FtpHelper工具类:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;
public class FtpHelper {
public static int batch = 0;
private static Logger log = Logger.getLogger(FtpHelper.class);
public FtpHelper() {
}
public static boolean uploadFile(String url, int port, String username, String password, String path, String filename, InputStream input) {
boolean success = false;
FTPClient ftp = new FTPClient();
try {
ftp.setControlEncoding("UTF-8");
ftp.connect(url);
boolean isLogin = ftp.login(username, password);
log.info("-----FTPupload--------------------FTP服务器连接状态: " + isLogin);
log.info("-----FTPupload--------------------FTP服务器返回码: " + ftp.getReplyCode());
boolean ret = false;
ret = ftp.setFileType(2);
log.info("-----FTPupload--------------------FTP服务器连接状态(setfiletype): " + ret);
ret = ftp.makeDirectory(path);
log.info("-----FTPupload--------------------FTP服务器连接状态(makeDirectory): " + ret);
ret = ftp.changeWorkingDirectory(path);
log.info("-----FTPupload--------------------FTP服务器连接状态(changeWorkingDirectory): " + ret);
ftp.enterLocalPassiveMode();
ret = ftp.storeFile(filename, input);
log.info("-----FTPupload--------------------FTP服务器连接状态(storeFile): " + ret);
ret = ftp.logout();
log.info("-----FTPupload--------------------FTP服务器连接状态(logout): " + ret);
success = true;
log.info("-----FTPupload--------------------FTP服务器上传文件完成");
} catch (IOException var19) {
log.info("-----FTPupload--------------------FTP服务器上传文件异常: " + var19.getMessage());
var19.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
input.close();
} catch (IOException var18) {
log.info("-----FTPupload--------------------FTP服务器上传 uploadFile 关闭操作出错: " + var18.getMessage());
var18.printStackTrace();
}
}
log.info("-----FTPupload--------------------FTP服务器上传文件结束end");
}
return success;
}
public static boolean downFile(String url, int port, String username, String password, String remotePath, String fileName, String localPath, String realpath, String htout) {
boolean success = false;
FTPClient ftp = new FTPClient();
try {
boolean ret = false;
ftp.setControlEncoding("UTF-8");
ftp.connect(url);
ret = ftp.login(username, password);
log.info("-----FTPdownload--------------------FTP服务器连接状态: " + ret);
log.info("-----FTPdownload--------------------FTP服务器返回码: " + ftp.getReplyCode());
ret = ftp.changeWorkingDirectory(remotePath);
if (htout != "") {
ftp.changeWorkingDirectory(htout);
}
ftp.enterLocalPassiveMode();
log.info("-----FTPdownload--------------------FTP服务器连接状态(changeWorkingDirectory): " + ret);
FTPFile[] fs = ftp.listFiles();
log.info("-----FTPdownload--------------------FTP服务器包含文件名: " + ftp.listNames());
FTPFile[] var13 = fs;
int var14 = fs.length;
for(int var15 = 0; var15 < var14; ++var15) {
FTPFile ff = var13[var15];
log.info("-----FTPdownload--------------------FTP服务器当前读到的文件: " + ff.getName());
if (ff.getName().equals(fileName)) {
File localFile = new File(new File(realpath), fileName);
if (!localFile.getParentFile().exists()) {
localFile.getParentFile().mkdirs();
}
OutputStream is = new FileOutputStream(new File(new File(realpath), fileName));
ret = ftp.retrieveFile(ff.getName(), is);
log.info("-----FTPdownload--------------------FTP服务器连接状态(retrieveFile): " + ret);
is.close();
success = true;
}
}
ret = ftp.logout();
log.info("-----FTPdownload--------------------FTP服务器连接状态(logout): " + ret);
} catch (Exception var27) {
log.info("-----FTPdownload--------------------FTP服务器连接状态(logout): " + var27.getMessage());
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException var26) {
;
}
}
}
return success;
}
public static boolean deleteFile(String hostname, int port, String username, String password, String pathname, String filename) {
boolean flag = false;
FTPClient ftp = new FTPClient();
try {
boolean ret = false;
int ret2 = false;
ftp.setControlEncoding("UTF-8");
ftp.connect(hostname, port);
ret = ftp.login(username, password);
log.info("-----ftpdel--------------------FTP服务器连接状态: " + ret);
log.info("-----ftpdel--------------------FTP服务器返回码: " + ftp.getReplyCode());
ret = ftp.changeWorkingDirectory(pathname);
log.info("-----ftpdel--------------------FTP服务器连接状态(changeWorkingDirectory) " + ret);
ftp.enterLocalPassiveMode();
int ret2 = ftp.dele(filename);
log.info("-----ftpdel--------------------FTP服务器连接状态(dele) " + ret2);
ret = ftp.logout();
log.info("-----ftpdel--------------------FTP服务器连接状态(logout) " + ret);
flag = true;
} catch (Exception var18) {
var18.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.logout();
} catch (IOException var17) {
var17.printStackTrace();
}
}
}
return flag;
}
}
docsHTML工具类代码:
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.OpenOfficeDocumentConverter;
import com.qtong.afin.core.util.ConfigurationInfo;
import org.apache.log4j.Logger;
import java.io.*;
import java.net.ConnectException;
/**
* 将Word文档转换成pdf的工具类
*
*
*/
public class Doc2Html {
private static Logger log = Logger.getLogger(Doc2Html.class);
/**
*
* @param contractWordUrl 合同是word的url
* @param name
* @return
*/
public static File uploadFile(String realPath,String contractWordUrl,String name){
File htmlString = toHtmlString(new File(contractWordUrl), realPath,name);
log.info("转成pdf的url;"+htmlString);
return htmlString;
}
/**
* 将word文档转换成html文档
*
* @param docFile
* 需要转换的word文档
* @param filepath
* 转换之后html的存放路径
* @return 转换之后的html文件
*/
public static File convert(File docFile, String filepath,String name) {
// 创建保存html的文件
File htmlFile = new File(filepath + "/" + name
+ ".pdf");
log.info("创建保存html的文件:"+htmlFile);
// 创建Openoffice连接
OpenOfficeConnection con = new SocketOpenOfficeConnection(8100);
try {
// 连接
con.connect();
} catch (ConnectException e) {
log.info("获取OpenOffice连接失败...");
e.printStackTrace();
}
// 创建转换器
DocumentConverter converter = new OpenOfficeDocumentConverter(con);
// 转换文档问html
converter.convert(docFile, htmlFile);
/* // 关闭openoffice连接
con.disconnect();*/
return htmlFile;
}
/**
* 将word转换成html文件,并且获取html文件代码。
*
* @param docFile
* 需要转换的文档
* @param filepath
* 文档中图片的保存位置
* @return 转换成功的html代码
*/
public static File toHtmlString(File docFile, String filepath,String name) {
// 转换word文档
File htmlFile = convert(docFile, filepath,name);
// 获取html文件流
StringBuffer htmlSb = new StringBuffer();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(htmlFile)));
while (br.ready()) {
htmlSb.append(br.readLine());
}
br.close();
// 删除临时文件
// htmlFile.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// HTML文件字符串
// 返回经过清洁的html文本
return htmlFile;
}
}
其中,openoffice转换pdf文档所需要的依赖,大概是这些,不对的自己找找,我找了好几天,终于不报错了。
有些jar包版本或者其他原因什么的,可能找不到,自己想想办法,比如:下载jar包,手动安装到本地仓库。
至于openoffice的安装方法和启动方式,自行百度,在转换PDF之前需开启openoffice。
pdf.js插件,自行百度下载。
<!--office文档在线预览-start-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.artofsolving</groupId>
<artifactId>jodconverter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.artofsolving</groupId>
<artifactId>jodconverter-cli</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>juh</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>jurt</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>ridl</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.openoffice</groupId>
<artifactId>unoil</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
<!--office文档在线预览-end-->
OK,完事,上效果图:
选择文件前:
选择文件后:
点击创建完成文件上传后,在本地硬盘上找到的其中一个文件:
点击下载后:
在线预览效果图:
对了,我使用的浏览器是谷歌,不过应该没影响。