提交 306fdcac authored 作者: wangmenglong's avatar wangmenglong

增加爬虫

上级 c645045d
......@@ -4,11 +4,12 @@ import base.controller.BaseController;
import base.result.BaseResult;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.jfb.recruit.bean.auth.UserContext;
import com.jfb.recruit.service.OrgService;
import com.jfb.recruit.service.RecruitService;
import com.jfb.recruit.util.auth.UserUtils;
import com.jfb.recruit.util.Excelutils.ExcelAppendUtil;
import com.jfb.recruit.util.Excelutils.JobsExcel;
import com.jfb.recruit.util.Excelutils.OrgExcel;
import com.jfb.recruit.util.Excelutils.OrgExcelAppendUtil;
import data.recruit.Org;
import data.recruit.Recruit;
import org.apache.commons.lang3.StringUtils;
......@@ -42,8 +43,167 @@ public class ImportRecruitController extends BaseController {
@Resource
OrgService orgService;
// 桌面的Excel文件名(可自定义,如:upload_record.xlsx)
private static final String EXCEL_FILE_NAME = "/pchongshuju/show.xlsx";
private static final String EXCEL_FILE_ORG_NAME = "/pchongshuju/showOrg.xlsx";
/**
* 文件上传接口
* @param file 上传的文件
* @param remark 备注(可选,前端传)
* @return 上传结果
*/
@PostMapping("/upload/job")
public BaseResult uploadFile(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "remark", defaultValue = "无备注") String remark) {
// 1. 校验文件是否为空
if (file.isEmpty()) {
return BaseResult.error("001");
}
// 2. 校验文件类型(增强严谨性,避免OOXML错误)
String originalFilename = file.getOriginalFilename();
// 优化:双重校验(后缀+内容类型,防止改后缀的非JSON文件)
if (originalFilename == null || !originalFilename.trim().toLowerCase().endsWith(".json")) {
return BaseResult.error("002");
}
// 可选:额外校验Content-Type,进一步防止非JSON文件
String contentType = file.getContentType();
if (contentType != null && !contentType.equalsIgnoreCase("application/json")
&& !contentType.equalsIgnoreCase("text/plain")) {
return BaseResult.error("002");
}
// 3. 读取文件全部内容(确保流仅用于文本读取,避免被Office解析库误处理)
StringBuilder jsonContent = new StringBuilder();
// 核心:仅用BufferedReader读取文本,不引入任何Office解析逻辑
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8) // 强制UTF-8,避免乱码
)) {
String line;
while ((line = reader.readLine()) != null) {
jsonContent.append(line);
}
JSONArray jsonArray = JSONArray.parseArray(jsonContent.toString());
// 3. 调用工具类追加数据(EasyExcel支持批量,这里单条也用列表)
List<JobsExcel> dataList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
// 2. 封装要追加到Excel的数据
JobsExcel jobsExcel = new JobsExcel();
jobsExcel.setJonName(jsonObject.getString("jobName"));
jobsExcel.setFullCompanyName(jsonObject.getString("fullCompanyName"));
jobsExcel.setJobSalaryMin(jsonObject.getString("jobSalaryMin"));
jobsExcel.setJobSalaryMax(jsonObject.getString("jobSalaryMax"));
jobsExcel.setJobDescribe(jsonObject.getString("jobDescribe"));
dataList.add(jobsExcel);
}
ExcelAppendUtil.appendDataToExcel(EXCEL_FILE_NAME, dataList);
// 4. 返回成功响应
return BaseResult.success(); // 优化:确保返回字符串类型
} catch (IOException e) {
return BaseResult.error("003");
}
}
/**
* 文件上传接口
* @param file 上传的文件
* @param remark 备注(可选,前端传)
* @return 上传结果
*/
@PostMapping("/upload/org")
public BaseResult uploadFileOrg(
@RequestParam("file") MultipartFile file,
@RequestParam(value = "remark", defaultValue = "无备注") String remark) {
// 1. 校验文件是否为空
if (file.isEmpty()) {
return BaseResult.error("001");
}
// 2. 校验文件类型(增强严谨性,避免OOXML错误)
String originalFilename = file.getOriginalFilename();
// 优化:双重校验(后缀+内容类型,防止改后缀的非JSON文件)
if (originalFilename == null || !originalFilename.trim().toLowerCase().endsWith(".json")) {
return BaseResult.error("002");
}
// 可选:额外校验Content-Type,进一步防止非JSON文件
String contentType = file.getContentType();
if (contentType != null && !contentType.equalsIgnoreCase("application/json")
&& !contentType.equalsIgnoreCase("text/plain")) {
return BaseResult.error("002");
}
// 3. 读取文件全部内容(确保流仅用于文本读取,避免被Office解析库误处理)
StringBuilder jsonContent = new StringBuilder();
// 核心:仅用BufferedReader读取文本,不引入任何Office解析逻辑
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8) // 强制UTF-8,避免乱码
)) {
String line;
while ((line = reader.readLine()) != null) {
jsonContent.append(line);
}
JSONArray jsonArray = JSONArray.parseArray(jsonContent.toString());
// 3. 调用工具类追加数据(EasyExcel支持批量,这里单条也用列表)
List<OrgExcel> dataList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
// 2. 封装要追加到Excel的数据
OrgExcel jobsExcel = new OrgExcel();
jobsExcel.setName(jsonObject.getString("name"));
jobsExcel.setIntro(jsonObject.getString("intro"));
jobsExcel.setAddress(jsonObject.getString("address"));
dataList.add(jobsExcel);
}
OrgExcelAppendUtil.appendDataToExcel(EXCEL_FILE_ORG_NAME, dataList);
// 4. 返回成功响应
return BaseResult.success(); // 优化:确保返回字符串类型
} catch (IOException e) {
return BaseResult.error("003");
}
}
/**
* 获取企业信息
* 获取企业url
* @return: base.result.BaseResult
* @Author: wml
* @Date 2026/1/12 15:33
......
package com.jfb.recruit.util.Excelutils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.jfb.recruit.util.Excelutils.JobsExcel;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 适配EasyExcel 2.2.10 + POI 3.17的Excel追加工具类(彻底解决空文件+覆盖问题)
*/
public class ExcelAppendUtil {
// 获取桌面Excel路径
public static String getDesktopExcelPath(String excelFileName) {
String desktopPath = System.getProperty("user.home") + File.separator + "Desktop";
return desktopPath + File.separator + excelFileName;
}
// 读取Excel中所有已有数据(2.2.10兼容写法)
private static List<JobsExcel> readAllExcelData(String excelPath) {
File excelFile = new File(excelPath);
// 空文件/不存在直接返回空列表
if (!excelFile.exists() || excelFile.length() == 0) {
return new ArrayList<>();
}
// 自定义监听器读取所有数据
class DataReadListener extends AnalysisEventListener<JobsExcel> {
private List<JobsExcel> dataList = new ArrayList<>();
@Override
public void invoke(JobsExcel data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
public List<JobsExcel> getDataList() {
return dataList;
}
}
DataReadListener listener = new DataReadListener();
try {
EasyExcel.read(excelPath, JobsExcel.class, listener)
.sheet("上传记录")
.doRead();
} catch (Exception e) {
System.out.println("读取Excel数据失败,将重新创建文件:" + e.getMessage());
return new ArrayList<>();
}
return listener.getDataList();
}
// 核心:追加数据(2.2.10兼容,零覆盖+空文件修复)
public static void appendDataToExcel(String excelFileName, List<JobsExcel> newData) {
String excelPath = getDesktopExcelPath(excelFileName);
File excelFile = new File(excelPath);
// ========== 第一步:最前置的空文件检测(关键!拦截所有空文件场景) ==========
if (excelFile.exists()) {
// 1. 空文件直接删除,避免POI解析报错
if (excelFile.length() == 0) {
excelFile.delete();
System.out.println("检测到空Excel文件,已删除:" + excelPath);
}
// 2. 非空文件但读取失败(损坏),也删除
else {
try {
// 尝试读取文件头,验证文件有效性
EasyExcel.read(excelPath).sheet("上传记录").doRead();
} catch (Exception e) {
excelFile.delete();
System.out.println("Excel文件损坏,已删除:" + e.getMessage());
}
}
}
try {
// ========== 第二步:读取原有数据 + 合并新数据 ==========
List<JobsExcel> allData = new ArrayList<>();
// 文件存在且有效:读取原有数据
if (excelFile.exists() && excelFile.length() > 0) {
allData = readAllExcelData(excelPath);
System.out.println("读取到原有Excel数据行数:" + allData.size());
}
// 合并新数据(核心:追加=原有数据+新数据)
allData.addAll(newData);
// ========== 第三步:重新写入(覆盖整个文件,但数据是合并后的,等价于追加) ==========
EasyExcel.write(excelPath, JobsExcel.class)
.sheet("上传记录")
.doWrite(allData);
// ========== 第四步:验证写入结果,避免生成空文件 ==========
if (!excelFile.exists() || excelFile.length() == 0) {
throw new RuntimeException("写入Excel失败:生成了空文件(桌面权限不足/文件被占用)");
}
System.out.println("数据追加成功!总数据行数:" + allData.size() + ",文件路径:" + excelPath);
} catch (Exception e) {
// 异常时清理空文件
if (excelFile.exists() && excelFile.length() == 0) {
excelFile.delete();
}
throw new RuntimeException("追加Excel数据失败:" + e.getMessage(), e);
}
}
}
\ No newline at end of file
package com.jfb.recruit.util.Excelutils;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* @ClassName : JobsExcel
* @Description :
* @Author : wml
* @Date: 2026-01-13 16:01
*/
@Data
public class JobsExcel {
// ExcelProperty:指定列名,index指定列索引(0开始)
@ExcelProperty(value = "职位名", index = 0)
private String jonName;
@ExcelProperty(value = "企业名", index = 1)
private String fullCompanyName;
@ExcelProperty(value = "薪资范围", index = 2)
private String jobSalaryMin;
@ExcelProperty(value = "薪资范围", index = 3)
private String jobSalaryMax;
@ExcelProperty(value = "工作内容", index = 4)
private String jobDescribe;
}
package com.jfb.recruit.util.Excelutils;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
/**
* @ClassName : JobsExcel
* @Description :
* @Author : wml
* @Date: 2026-01-13 16:01
*/
@Data
public class OrgExcel {
// ExcelProperty:指定列名,index指定列索引(0开始)
@ExcelProperty(value = "企业名", index = 0)
private String name;
@ExcelProperty(value = "地址", index = 1)
private String address;
@ExcelProperty(value = "企业简介", index = 2)
private String intro;
}
package com.jfb.recruit.util.Excelutils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 适配EasyExcel 2.2.10 + POI 3.17的Excel追加工具类(彻底解决空文件+覆盖问题)
*/
public class OrgExcelAppendUtil {
// 获取桌面Excel路径
public static String getDesktopExcelPath(String excelFileName) {
String desktopPath = System.getProperty("user.home") + File.separator + "Desktop";
return desktopPath + File.separator + excelFileName;
}
// 读取Excel中所有已有数据(2.2.10兼容写法)
private static List<OrgExcel> readAllExcelData(String excelPath) {
File excelFile = new File(excelPath);
// 空文件/不存在直接返回空列表
if (!excelFile.exists() || excelFile.length() == 0) {
return new ArrayList<>();
}
// 自定义监听器读取所有数据
class DataReadListener extends AnalysisEventListener<OrgExcel> {
private List<OrgExcel> dataList = new ArrayList<>();
@Override
public void invoke(OrgExcel data, AnalysisContext context) {
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {}
public List<OrgExcel> getDataList() {
return dataList;
}
}
DataReadListener listener = new DataReadListener();
try {
EasyExcel.read(excelPath, OrgExcel.class, listener)
.sheet("上传记录")
.doRead();
} catch (Exception e) {
System.out.println("读取Excel数据失败,将重新创建文件:" + e.getMessage());
return new ArrayList<>();
}
return listener.getDataList();
}
// 核心:追加数据(2.2.10兼容,零覆盖+空文件修复)
public static void appendDataToExcel(String excelFileName, List<OrgExcel> newData) {
String excelPath = getDesktopExcelPath(excelFileName);
File excelFile = new File(excelPath);
// ========== 第一步:最前置的空文件检测(关键!拦截所有空文件场景) ==========
if (excelFile.exists()) {
// 1. 空文件直接删除,避免POI解析报错
if (excelFile.length() == 0) {
excelFile.delete();
System.out.println("检测到空Excel文件,已删除:" + excelPath);
}
// 2. 非空文件但读取失败(损坏),也删除
else {
try {
// 尝试读取文件头,验证文件有效性
EasyExcel.read(excelPath).sheet("上传记录").doRead();
} catch (Exception e) {
excelFile.delete();
System.out.println("Excel文件损坏,已删除:" + e.getMessage());
}
}
}
try {
// ========== 第二步:读取原有数据 + 合并新数据 ==========
List<OrgExcel> allData = new ArrayList<>();
// 文件存在且有效:读取原有数据
if (excelFile.exists() && excelFile.length() > 0) {
allData = readAllExcelData(excelPath);
System.out.println("读取到原有Excel数据行数:" + allData.size());
}
// 合并新数据(核心:追加=原有数据+新数据)
allData.addAll(newData);
// ========== 第三步:重新写入(覆盖整个文件,但数据是合并后的,等价于追加) ==========
EasyExcel.write(excelPath, OrgExcel.class)
.sheet("上传记录")
.doWrite(allData);
// ========== 第四步:验证写入结果,避免生成空文件 ==========
if (!excelFile.exists() || excelFile.length() == 0) {
throw new RuntimeException("写入Excel失败:生成了空文件(桌面权限不足/文件被占用)");
}
System.out.println("数据追加成功!总数据行数:" + allData.size() + ",文件路径:" + excelPath);
} catch (Exception e) {
// 异常时清理空文件
if (excelFile.exists() && excelFile.length() == 0) {
excelFile.delete();
}
throw new RuntimeException("追加Excel数据失败:" + e.getMessage(), e);
}
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论