网页查看附件功能,查看附件(转为PDF格式查看的)-未验证
1.效果图-答辩项目有
就是在单独的一个浏览器页面 查询附件内容
2.简单看下前端
<el-button type="text" size="small" @click="viewFile(scope.row)">
查看
</el-button>
点击查看案件 触发下面这个方法
viewFile(row) {
if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(row.attachmentType.toLowerCase())) {
previewFile({ attachmentUrl: row.attachmentUrl.replace(/\\/g, ',') }).then(res => {
const blob = new Blob([res.data], { type: 'application/pdf' })
const src = window.URL.createObjectURL(blob)
window.open(src)
})
} else {
fileApi
.viewFile({ attachmentUrl: row.attachmentUrl, attachmentType: row.attachmentType, attachmentName: row.attachmentName }).then(res => {
if (res.status === 200 && res.data) {
const obj = {
pdf: 'application/pdf',
aac: 'audio/aac',
abw: 'application/x-abiword',
arc: 'application/x-freearc',
avi: 'video/x-msvideo',
css: 'text/css',
csv: 'text/csv',
doc: 'application/msword',
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
gif: 'image/gif',
htm: 'text/html',
html: 'text/html',
ico: 'image/vnd.microsoft.icon',
ics: 'text/calendar',
jar: 'application/java-archive',
jpeg: 'image/jpeg',
jpg: 'image/jpeg',
js: 'text/javascript',
json: 'application/json',
mp3: 'audio/mpeg',
mpeg: 'video/mpeg',
png: 'image/png',
ppt: 'application/vnd.ms-powerpoint',
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
rar: 'application/x-rar-compressed',
svg: 'image/svg+xml',
tif: 'image/tiff',
tiff: 'image/tiff',
txt: 'text/plain',
vsd: 'application/vnd.visio',
wav: 'audio/wav',
weba: 'audio/webm',
webm: 'video/webm',
webp: 'image/webp',
xls: 'application/vnd.ms-excel',
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
zip: 'application/zip'
}
const blob = new Blob([res.data], { type: obj[row.attachmentType.toLowerCase()] })
const src = window.URL.createObjectURL(blob)
if (['jpg', 'jpeg', 'png', 'svg', 'gif'].includes(row.attachmentType.toLowerCase())) {
this.imgsVisible = true
this.imgUrlList.push(src)
} else if (['pdf'].includes(row.attachmentType.toLowerCase())) {
window.open(src)
} else {
this.$message.error('该附件无法打开')
}
} else {
this.$message.error('查看失败')
}
})
}
},
previewFile然后会触发这个请求
import axios from './index'
export function previewFile(params) {
return axios.request({
url: 'secured/file/preview',
method: 'get',
responseType: 'blob',
params
})
}
chatGPT解读前端代码
这段代码中的viewFile方法用于查看文件。它接收一个row参数,该参数包含了文件的相关信息,如附件类型(attachmentType)、附件URL(attachmentUrl)和附件名称(attachmentName)。
首先,它检查附件类型是否属于文档(doc、docx、xls、xlsx、ppt、pptx)之一。如果是,它会调用previewFile方法预览文件。该方法会将附件URL中的反斜杠(\)替换为逗号(,),然后获取文件内容并创建一个Blob对象,最后通过URL.createObjectURL生成预览文件的URL,并在新窗口中打开。
如果附件类型不属于文档类型,则调用fileApi.viewFile方法来查看文件。该方法接收附件的URL、类型和名称作为参数。如果请求成功并且返回了文件内容(状态码为200且存在数据),则根据附件类型在预定义的对象obj中查找对应的MIME类型。然后,它创建一个Blob对象,再次使用URL.createObjectURL生成文件的URL。
最后,根据文件类型进行判断。如果是图片类型(jpg、jpeg、png、svg、gif),它将图片的URL添加到imgUrlList数组中,并将imgsVisible标志设置为true,以显示图片预览。如果是PDF类型,直接在新窗口中打开PDF文件。对于其他类型的文件,则显示错误消息,表示无法打开该附件。
总体而言,该viewFile方法用于根据附件类型预览或打开文件,并根据文件类型执行不同的操作。
3.看后台控制层
/**
* 文件预览(转成pdf后预览)
*/
@GetMapping(FILE_PREVIEW)
public void preview(String attachmentUrl, HttpServletResponse response){
//路径中的反斜杠会有些问题, 前后端统一协商处理
attachmentUrl = attachmentUrl.replaceAll(",", "/");
fileService.preview(attachmentUrl, response);
}
4. service层
/**
* 将文件转为pdf之后预览
* @param path
* @param response
*/
void preview(String path, HttpServletResponse response);
@Override
public void preview(String path, HttpServletResponse response) {
if(StringUtils.isEmpty(path)){
throw new IllegalStateException("文件为空");
}
//取文件类型
String type = path.substring(path.lastIndexOf('.')+1);
if(StringUtils.isEmpty(type)){
throw new IllegalStateException("未知文件类型");
}
response.setContentType("application/pdf");
response.setHeader("content-disposition","attachment; filename=temp.pdf");
//文件解密
//==fileTempDir ==》./file/temp/
String tempPath = FileSystems.getDefault().getPath(
fileTempDir,
UUID.randomUUID().toString() + "."
+ getFileExtension(path).toLowerCase()
).toString();
try {
DecFile(path, tempPath);
} catch (Exception e) {
throw new IllegalStateException("文件解密失败");
}
File file = new File(tempPath);
try(InputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream()) {
//根据不同类型,进行不同方式地转换
switch (type.toLowerCase(Locale.ROOT)) {
case "pdf":
byte[] buf = new byte[8192];
int c = 0;
while ((c = in.read(buf)) > 0) {
out.write(buf);
out.flush();
}
break;
case "doc":
case "docx":
Document doc = new Document(in);
//不显示修改记录
doc.acceptAllRevisions();
doc.save(out, SaveFormat.PDF);
break;
case "xls":
case "xlsx":
//破解了认证,调用一下过一下认证
InputStream inputStream = null;
License license = new License();
license.setLicense(inputStream);
Workbook excel = new Workbook(in);
excel.save(out, com.aspose.cells.SaveFormat.PDF);
break;
case "ppt":
case "pptx":
//破解了认证,用个假的license忽悠一下
InputStream inputStream2 = FileServiceImpl.class.getClassLoader().getResourceAsStream("license.xml");
com.aspose.slides.License license2 = new com.aspose.slides.License();
license2.setLicense(inputStream2);
Presentation ppt = new Presentation(in);
ppt.save(out, com.aspose.slides.SaveFormat.Pdf);
break;
default:
throw new IllegalStateException("无法转换的文件类型");
}
} catch (Exception e) {
throw new IllegalStateException("文件转换异常", e);
}
//删除解密的临时文件
delete(tempPath);
}
4. service层中转换为PDF需要的maven
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>22.11.2</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-slides</artifactId>
<version>22.10.2</version>
</dependency>
5.解读service层(以及设计的公共方法)
1.判断文件是否为空
2.判断文件类型
3.设置响应头信息
4.对文件进行解密(存到一个临时目录下) ==》在下面这个工具类
5.开始根据不同类型,进行不同方式的转换 都转换为PDF进行查看
6.删除解密的临时目录文件 ==》在下面删除文件的工具类
6.文件加密解密工具类
package com.safesoft.utils;
import java.io.*;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* @Author Sherlock.shen
* @Date 2021/12/15 13:52
* @Description: 文件加密解密
*/
public class EncryptUtils {
private static String key = "ajksdfjks&^%$$^Q**";
private static int[] array = string2ASCII(getMD5(key));
; //存放每个hash值的数组
/**
* 文件加密
* @param srcFileUrl 源文件的路径(就是源文件在哪里,名字也要带上的)
* @param encFileUrl 加密后的文件路径
* @throws Exception
*/
public static void EncFile(String srcFileUrl, String encFileUrl) throws Exception {
File srcFile = new File(srcFileUrl);
File encFile = new File(encFileUrl);
if (!srcFile.exists()) {
System.out.println("source file not exixt");
return;
}
if (!encFile.exists()) {
System.out.println("encrypt file created");
encFile.createNewFile();
}
InputStream fis = new FileInputStream(srcFile);
OutputStream fos = new FileOutputStream(encFile);
byte[] data = new byte[1024 * 1024 * 1024];
int length ;
int i = 0;
while ((length = fis.read(data)) > -1) {
for (int j = 0; j < length; j++) {
data[j] = (byte) (data[j] ^ array[i++]);
if (i == array.length - 1) i = 0;
}
fos.write(data, 0, length);
}
fis.close();
fos.flush();
fos.close();
}
/**
* 文件解密
* @param encFileUrl 需要解密的源文件的路径(就是源文件在哪里,名字也要带上的)
* @param decFileUrl 解密后的文件路径
* @throws Exception
*/
public static void DecFile(String encFileUrl, String decFileUrl) throws Exception {
File encFile = new File(encFileUrl);
File decFile = new File(decFileUrl);
if (!encFile.exists()) {
System.out.println("encrypt file not exixt");
return;
}
if (!decFile.exists()) {
System.out.println("decrypt file created");
decFile.createNewFile();
}
InputStream fis = new FileInputStream(encFile);
OutputStream fos = new FileOutputStream(decFile);
byte[] data = new byte[1024 * 1024 * 1024];
int length ;
int i = 0;
while ((length = fis.read(data)) > -1) {
for (int j = 0; j < length; j++) {
data[j] = (byte) (data[j] ^ array[i++]);
if (i == array.length - 1) i = 0;
}
fos.write(data, 0, length);
}
fis.close();
fos.flush();
fos.close();
}
/**
*字符串转换为对应的ASCII码数组
*
* @param s 字符串
* @return ASCII码
*/
public static int[] string2ASCII(String s) {// 字符串转换为ASCII码
if (s == null || "".equals(s)) {
return null;
}
char[] chars = s.toCharArray();
int[] asciiArray = new int[chars.length];
for (int i = 0; i < chars.length; i++) {
asciiArray[i] = char2ASCII(chars[i]);
}
return asciiArray;
}
public static int char2ASCII(char c) {
return (int) c;
}
/**
* 计算字符串的MD5哈希值
*
* @param sInput 字符串
* @return 哈希值转换为十六进制字符串并返回。
*/
public static String getMD5(String sInput) {
String algorithm = "";
if (sInput == null) {
return "null";
}
try {
algorithm = System.getProperty("MD5.algorithm", "MD5");
} catch (SecurityException se) {
}
MessageDigest md = null;
try {
md = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte buffer[] = sInput.getBytes();
for (int count = 0; count < sInput.length(); count++) {
md.update(buffer, 0, count);
}
byte bDigest[] = md.digest();
BigInteger bi = new BigInteger(bDigest);
return (bi.toString(16));
}
}
7.文件删除的工具类(删除文件,删除单个文件,删除目录)
package com.electronic.web.controller.studyFileView;
import java.io.File;
/**
* @Author Sherlock.shen
* @Date 2021/12/15 10:14
* @Description: 文件工具类
*/
public class FileDeleteUtils {
/**
* 删除文件,可以是文件或文件夹
*
* @param fileName 要删除的文件名
* @return 删除成功返回true,否则返回false
*/
public static boolean delete(String fileName) {
File file = new File(fileName);
if (!file.exists()) {
return false;
} else {
if (file.isFile())
return deleteFile(fileName);
else
return deleteDirectory(fileName);
}
}
/**
* 删除单个文件
*
* @param fileName 要删除的文件的文件名
* @return 单个文件删除成功返回true,否则返回false
*/
public static boolean deleteFile(String fileName) {
File file = new File(fileName);
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
/**
* 删除目录及目录下的文件
*
* @param dir 要删除的目录的文件路径
* @return 目录删除成功返回true,否则返回false
*/
public static boolean deleteDirectory(String dir) {
// 如果dir不以文件分隔符结尾,自动添加文件分隔符
if (!dir.endsWith(File.separator))
dir = dir + File.separator;
File dirFile = new File(dir);
// 如果dir对应的文件不存在,或者不是一个目录,则退出
if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
return false;
}
boolean flag = true;
// 删除文件夹中的所有文件包括子目录
File[] files = dirFile.listFiles();
for (int i = 0; i < files.length; i++) {
// 删除子文件
if (files[i].isFile()) {
flag = deleteFile(files[i].getAbsolutePath());
if (!flag)
break;
}
// 删除子目录
else if (files[i].isDirectory()) {
flag = deleteDirectory(files[i]
.getAbsolutePath());
if (!flag)
break;
}
}
if (!flag) {
return false;
}
return true;
// 删除当前目录
/* if (dirFile.delete()) {
return true;
} else {
return false;
}*/
}
}
break;
}
// 删除子目录
else if (files[i].isDirectory()) {
flag = deleteDirectory(files[i]
.getAbsolutePath());
if (!flag)
break;
}
}
if (!flag) {
return false;
}
return true;
// 删除当前目录
/* if (dirFile.delete()) {
return true;
} else {
return false;
}*/
}
}