本文目录导读:

我来介绍几种常见的Java文件预览方案和开发案例:
PDF文件预览
使用PDF.js实现Web端预览
// 后端 - Spring Boot控制器
@RestController
public class PDFPreviewController {
@GetMapping("/preview/pdf/{fileId}")
public ResponseEntity<Resource> previewPDF(@PathVariable String fileId) {
try {
// 从文件系统或数据库获取文件
File file = new File("/path/to/files/" + fileId + ".pdf");
Path path = file.toPath();
Resource resource = new UrlResource(path.toUri());
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.header(HttpHeaders.CONTENT_DISPOSITION,
"inline; filename=\"" + file.getName() + "\"")
.body(resource);
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
}
<!-- 前端HTML -->
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js"></script>
<style>
#pdf-container {
width: 100%;
height: 800px;
overflow: auto;
}
.page {
margin: 10px auto;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div id="pdf-container"></div>
<script>
// 加载PDF文件
const url = '/preview/pdf/test123';
pdfjsLib.getDocument(url).promise.then(function(pdf) {
const container = document.getElementById('pdf-container');
for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
pdf.getPage(pageNum).then(function(page) {
const scale = 1.5;
const viewport = page.getViewport({scale: scale});
const canvas = document.createElement('canvas');
canvas.className = 'page';
canvas.height = viewport.height;
canvas.width = viewport.width;
container.appendChild(canvas);
const context = canvas.getContext('2d');
page.render({
canvasContext: context,
viewport: viewport
});
});
}
});
</script>
</body>
</html>
Office文档预览(Word/Excel/PPT)
使用Apache POI转换为HTML
// 添加Maven依赖
/*
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
*/
public class OfficePreviewConverter {
// 转换Word为HTML
public String convertWordToHtml(InputStream inputStream) {
try {
XWPFDocument document = new XWPFDocument(inputStream);
XHTMLOptions options = XHTMLOptions.create();
ByteArrayOutputStream out = new ByteArrayOutputStream();
XHTMLConverter.getInstance().convert(document, out, options);
return out.toString("UTF-8");
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
// 转换Excel为HTML
public String convertExcelToHtml(InputStream inputStream) {
try {
Workbook workbook = WorkbookFactory.create(inputStream);
StringBuilder html = new StringBuilder();
html.append("<table border='1' style='border-collapse: collapse;'>");
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
for (Sheet sheet : workbook) {
html.append("<tr><td colspan='10'><b>").append(sheet.getSheetName()).append("</b></td></tr>");
for (Row row : sheet) {
html.append("<tr>");
for (Cell cell : row) {
String cellValue = getCellValue(cell, evaluator);
html.append("<td>").append(cellValue).append("</td>");
}
html.append("</tr>");
}
}
html.append("</table>");
return html.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private String getCellValue(Cell cell, FormulaEvaluator evaluator) {
switch (cell.getCellType()) {
case STRING:
return cell.getStringCellValue();
case NUMERIC:
if (DateUtil.isCellDateFormatted(cell)) {
return cell.getDateCellValue().toString();
}
return String.valueOf(cell.getNumericCellValue());
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
return getCellValue(evaluator.evaluateInCell(cell), evaluator);
default:
return "";
}
}
}
图片预览
@RestController
public class ImagePreviewController {
@GetMapping("/preview/image/{fileId}")
public ResponseEntity<byte[]> previewImage(@PathVariable String fileId) {
try {
// 读取图片文件
File file = new File("/path/to/images/" + fileId);
byte[] imageBytes = Files.readAllBytes(file.toPath());
// 判断图片类型
String contentType = Files.probeContentType(file.toPath());
if (contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.contentLength(imageBytes.length)
.body(imageBytes);
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
}
<!-- 前端 --> <img src="/preview/image/test123" alt="图片预览" style="max-width: 100%;">
文本文件预览
@RestController
public class TextPreviewController {
@GetMapping("/preview/text/{fileId}")
public ResponseEntity<String> previewText(@PathVariable String fileId) {
try {
File file = new File("/path/to/files/" + fileId);
String content = Files.readString(file.toPath());
return ResponseEntity.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(content);
} catch (Exception e) {
return ResponseEntity.notFound().build();
}
}
}
通用文件预览接口
@RestController
public class FilePreviewController {
@GetMapping("/preview/file/{fileId}")
public ResponseEntity<?> previewFile(@PathVariable String fileId) {
try {
File file = new File("/path/to/files/" + fileId);
String fileName = file.getName();
String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
switch (extension) {
case "pdf":
return previewPDF(file);
case "jpg":
case "jpeg":
case "png":
case "gif":
return previewImage(file);
case "txt":
case "log":
case "xml":
case "json":
case "html":
return previewText(file);
case "doc":
case "docx":
return previewWord(file);
case "xls":
case "xlsx":
return previewExcel(file);
default:
return ResponseEntity.badRequest().body("不支持的文件格式: " + extension);
}
} catch (Exception e) {
return ResponseEntity.internalServerError().body("文件预览失败: " + e.getMessage());
}
}
private ResponseEntity<?> previewPDF(File file) throws Exception {
Resource resource = new UrlResource(file.toPath().toUri());
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF)
.body(resource);
}
private ResponseEntity<byte[]> previewImage(File file) throws Exception {
byte[] bytes = Files.readAllBytes(file.toPath());
String contentType = Files.probeContentType(file.toPath());
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.body(bytes);
}
private ResponseEntity<String> previewText(File file) throws Exception {
String content = Files.readString(file.toPath());
return ResponseEntity.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(content);
}
private ResponseEntity<String> previewWord(File file) throws Exception {
// 使用Apache POI转换
OfficePreviewConverter converter = new OfficePreviewConverter();
String html = converter.convertWordToHtml(new FileInputStream(file));
return ResponseEntity.ok()
.contentType(MediaType.TEXT_HTML)
.body(html);
}
private ResponseEntity<String> previewExcel(File file) throws Exception {
OfficePreviewConverter converter = new OfficePreviewConverter();
String html = converter.convertExcelToHtml(new FileInputStream(file));
return ResponseEntity.ok()
.contentType(MediaType.TEXT_HTML)
.body(html);
}
}
使用第三方服务(如Office Online)
// 使用微软Office Online预览
@PostMapping("/preview/office-online")
public ResponseEntity<String> getOfficeOnlineUrl(@RequestBody FileInfo fileInfo) {
String wopiUrl = "https://your-domain.com/wopi/files/" + fileInfo.getFileId();
String accessToken = generateAccessToken(fileInfo);
String actionUrl = "https://view.officeapps.live.com/op/view.aspx?src=" +
URLEncoder.encode(wopiUrl, "UTF-8") +
"&access_token=" + accessToken;
return ResponseEntity.ok(actionUrl);
}
Spring Boot配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 配置文件上传大小
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(104857600); // 100MB
resolver.setMaxUploadSizePerFile(52428800); // 50MB
return resolver;
}
// 配置文件存储路径
@Value("${file.storage.path}")
private String storagePath;
@Bean
public void initStorage() {
File directory = new File(storagePath);
if (!directory.exists()) {
directory.mkdirs();
}
}
}
# application.yml
file:
storage:
path: /data/files
spring:
servlet:
multipart:
enabled: true
max-file-size: 50MB
max-request-size: 100MB
使用建议
-
安全性考虑:
- 实现文件访问权限控制
- 防止路径遍历攻击
- 限制文件类型和大小
-
性能优化:
- 使用缓存机制
- 异步处理大文件
- 限制并发预览数量
-
前端适配:
- 支持移动端自适应
- 提供下载选项
- 显示加载进度
这是一个完整的Java文件预览解决方案,你可以根据具体需求选择合适的方案进行实现。