需求:根据指定的路径下模版进行解析 将模版上传到指定的文件服务器。
1:将路径下的excel文件进行解析 下载
A:创建excel表格对应的字段注解 ExcelColumn
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelColumn {int index() default -1; // 列的索引,从0开始String name() default ""; // 列名,可以与Excel中的标题对应}
B:建立一个excel映射的实体对象
@ExcelColumn(index = 1, name = "A")
private String A;
@ExcelColumn(index = 2, name = "B")
private String B;
上述的属性A B的index对应excel的标题头的第几列的字段值
C:为了方便后续解析任意的excel文件 故创建一个文件解析工具 ExcelParserUtil.java
/*** excel解析工具类** @param inputStream* @param clazz* @param <T>* @return*/public static <T> List<T> parseExcel(InputStream inputStream, Class<T> clazz) throws Exception {List<T> result = new ArrayList<>();List<String> failReasonList = new ArrayList<>();int execRow = 1;try (Workbook workbook = new XSSFWorkbook(inputStream)) {Sheet sheet = workbook.getSheetAt(0); //第一个工作表Row headerRow = sheet.getRow(0); //第一行是标题行// 读取实体类的字段注解,构建字段名和列索引的映射Map<String, Integer> fieldIndexMap = new HashMap<>();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {ExcelColumn excelColumn = field.getAnnotation(ExcelColumn.class);if (excelColumn != null && excelColumn.index() >= 0) {field.setAccessible(true);fieldIndexMap.put(field.getName(), excelColumn.index());}}// 跳过标题行,从第二行开始解析数据for (int i = 1; i <= sheet.getLastRowNum(); i++) {Row row = sheet.getRow(i);T instance = clazz.getDeclaredConstructor().newInstance();for (Map.Entry<String, Integer> entry : fieldIndexMap.entrySet()) {try {String fieldName = entry.getKey();int columnIndex = entry.getValue();Cell cell = row.getCell(columnIndex);if (cell != null) {Field field = clazz.getDeclaredField(fieldName);setFieldValue(instance, field, cell);}} catch (Exception e) {failReasonList.add("第" + execRow + "行解析错误:" + e.getMessage());}}execRow++;result.add(instance);}} catch (Exception e) {throw new Exception("parseExcel->数据解析错误:", e);}if (CollectionUtils.isNotEmpty(failReasonList)) {throw new Exception(JSON.toJSONString(failReasonList.subList(0, failReasonList.size() > 20 ? 20 : failReasonList.size())));}return result;}
/*** 方法setFieldValue 主要用于给每个单元格进行设置对应的值。* @param instance* @param field* @param cell* @throws IllegalAccessException* @throws InvocationTargetException*/private static void setFieldValue(Object instance, Field field, Cell cell) throws IllegalAccessException, InvocationTargetException {Class<?> fieldType = field.getType();field.setAccessible(true);// 总是将Cell设置为STRING类型,以确保我们可以获取字符串值cell.setCellType(CellType.STRING);String cellValue = cell.getStringCellValue();if (String.class.equals(fieldType)) {field.set(instance, cell.getStringCellValue());} else if (Integer.class.equals(fieldType) || int.class.equals(fieldType)) {field.setInt(instance, Integer.parseInt(cellValue));} else if (Long.class.equals(fieldType) || long.class.equals(fieldType)) {field.setLong(instance, Long.parseLong(cellValue));} else if (Double.class.equals(fieldType) || double.class.equals(fieldType)) {field.setDouble(instance, Double.parseDouble(cellValue));} else if (Boolean.class.equals(fieldType) || boolean.class.equals(fieldType)) {field.setBoolean(instance, Boolean.parseBoolean(cellValue));} else {throw new RuntimeException("Unsupported field type: " + fieldType.getName());}}/*** 指定下载的文件路径 将文件流保存到执行的的位置** @param url* @param savePath* @return*/public static String download(String url, String savePath) {InputStream inputStream = null;FileOutputStream fos = null;try {URL u = new URL(url);HttpURLConnection conn = (HttpURLConnection) u.openConnection();//设置超时间为3秒conn.setConnectTimeout(HTTP_CONNECT_TIMEOUT);//防止屏蔽程序抓取而返回403错误conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");//得到输入流inputStream = conn.getInputStream();//获取自己数组byte[] getData = readInputStream(inputStream);File file = new File(savePath);
// 文件保存位置createDir(file);fos = new FileOutputStream(file);fos.write(getData);} catch (IOException e) {} finally {try {if (fos != null) {fos.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {}}return savePath;}/*** 从输入流中获取字节数组** @param inputStream* @return* @throws IOException*/private static byte[] readInputStream(InputStream inputStream) throws IOException {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while ((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();}/*** 根据文件创建目录** @param file*/public static void createDir(File file) {if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}}
D:使用上述工具类进行文件的解析和下载功能演练
//下载路径private static final String downloadUrl = "https://xxx.com.cn/files/";//模版位置private static final String templateUrl = "E:/source";//下载文件存放位置private static final String saveUrl = "E:/source/downlod";private static final String handCompany = "1-A.xlsx";private static final String company = "2-B.xlsx";private static final String industry = "3-C.xlsx";public static void main(String[] args) {ExcelParserUtil parser = new ExcelParserUtil();try {File file = new File(templateUrl); // 替换为你的文件路径File[] files = file.listFiles();for (File fileItem : files) {if (fileItem.isFile()) {InputStream inputStream = new FileInputStream(fileItem);if (inputStream != null) {String fileName = fileItem.getName();List<ExcelEntity> excelEntities = parser.parseExcel(inputStream, ExcelEntity.class);exec(excelEntities, parser, fileName);}}}} catch (Exception e) {e.printStackTrace();}}private static void exec(List<ExcelEntity> entityList, ExcelParserUtil parser, String fileName) {List<String> list = new ArrayList<>();// 输出解析结果System.out.println("解析了数据:" + entityList.size());for (ExcelEntity entity : entityList) {//得到解析的文件数据做自己的业务逻辑处理。String finalUrl = downloadUrl + fileUrl;//处理投资池证券导入模板文件路径字段String download = parser.download(finalUrl, saveUrl + File.separator + "新的文件名称");}}
2:上传文件到执行服务器
/*** 上传文件* @param filePath* @param typeId* @return*/public static R upload(String filePath, String typeId) {CloseableHttpClient httpClient = HttpClientBuilder.create().build();CloseableHttpResponse httpResponse = null;RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000000).build();HttpPost httpPost = new HttpPost(baseUrl + PREFIX + "/service/files/upload");httpPost.setConfig(requestConfig);MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);multipartEntityBuilder.setCharset(Charset.forName("UTF-8"));File file = new File(filePath);if (FrameStringUtil.isNotEmpty(typeId)) {multipartEntityBuilder.addPart("typeId", new StringBody(typeId, ContentType.create("text/plain", Consts.UTF_8)));}HttpEntity httpEntity = multipartEntityBuilder.build();httpPost.setEntity(httpEntity);try {httpResponse = httpClient.execute(httpPost);HttpEntity responseEntity = httpResponse.getEntity();int statusCode= httpResponse.getStatusLine().getStatusCode();if(statusCode == 200) {BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent()));StringBuffer buffer = new StringBuffer();String str = "";while(FrameStringUtil.isNotEmpty(str = reader.readLine())) {buffer.append(str);}String result = buffer.toString();R.setBody(result);R.setSucc();//post(url, params);}httpClient.close();if(httpResponse != null) {httpResponse.close();}} catch (IOException e) {e.printStackTrace();R.setCode(-1001);R.setMessage("上传文件到文件管理服务失败: " + e.getMessage());}return R;}
3:文件基础相关操作
/*** 删除指定零时目录下的文件** @param sourceUrl* @param destinationUrl* @param fileName* @return*/
public static Boolean deleteFilesInDirectory(String tempUrl) {Boolean delFlag = false;File directory = new File(tempUrl);if (directory.exists() && directory.isDirectory()) {File[] files = directory.listFiles();if (files != null) {for (File file : files) {if (file.isFile()) {file.delete();delFlag = true;log.info("Deleted file: {}", file.getName());}}} else {log.info("The directory is empty.....");delFlag = false;}} else {delFlag = false;log.info("The directory does not exist or is not a directory.");}return delFlag;}
/*** 将byte[]转成File** @param sourceUrl* @param destinationUrl* @param fileName* @return*/public static File byteToFile(byte[] bytes, String path, String name) throws IOException {File dir = new File(path);if (!dir.exists() && !dir.isDirectory()) {//判断文件目录是否存在dir.mkdirs();}File file = new File(path + File.separator + name);FileOutputStream fout = new FileOutputStream(file);BufferedOutputStream bout = new BufferedOutputStream(fout);bout.write(bytes);return file;}/*** 文件复制转移** @param sourceUrl* @param destinationUrl* @param fileName* @return*/public static String copyFile(String sourceUrl, String destinationUrl, String fileName) {String fileTempUrl = "";File sourceFile = new File(sourceUrl);fileTempUrl = destinationUrl + File.separator + fileName;File destinationFile = new File(fileTempUrl);try {FileUtils.copyFile(sourceFile, destinationFile);log.info("文件复制成功!");} catch (IOException e) {log.info("文件复制失败!");System.out.println("文件复制失败!" + e.getMessage());}return fileTempUrl;}
4:文件相关操作工具类
/*** 创建指定路径的文件夹[不存在,则创建]* @param destDirName*/public static void createDir(String destDirName) {File dir = new File(destDirName);if(dir.exists()) {LOGGER.info("目录" + destDirName + "已存在!");} else {if(!destDirName.endsWith(File.separator)) {destDirName = destDirName + File.separator;}//创建目录dir.mkdirs();}}
/*** 读取文件[不存在,则创建]* @param destFileName 文件名* @return 创建成功返回true,否则返回false* @throws IOException*/public static File readFile(String destFileName) throws IOException {File file = new File(destFileName);if (file.exists()) {//LOGGER.info("目标文件已存在: " + destFileName);return file;}if (!file.getParentFile().exists()) {if (!file.getParentFile().mkdirs()) {LOGGER.info("创建目录文件所在的目录失败!");}}//创建目标文件if (file.createNewFile()) {LOGGER.info("创建单个文件成功: " + destFileName);} else {LOGGER.info("创建单个文件失败: " + destFileName);}return file;}
/*** 读取文件为byte[]* @param destFileName* @return*/public static byte[] readFileBytes(String destFileName) {try {BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(destFileName));int len = bufferedInputStream.available();byte[] bytes = new byte[len];int r = bufferedInputStream.read(bytes);if (len != r) {bytes = null;LOGGER.error("读取文件不正确");}bufferedInputStream.close();return bytes;} catch (FileNotFoundException e) {LOGGER.error(e.getMessage(), e);}catch (IOException e) {LOGGER.error(e.getMessage(), e);}return null;}
/*** 根据目录获取下面为指定文件名的文件* @param dir* @param filename* @return*/public static List<String> getFiles(String dir, String filename) {List<String> list = new ArrayList<String>();Map<String, List<String>> map = getDirFile(dir, true);List<String> allList = map.get("files");if(allList == null) {list = new ArrayList<String>();} else {for (String string : allList) {if(string.endsWith(File.separator + filename)) {list.add(string);}}}return list;}
/*** 获取目录下的文件和文件夹* @param dir* @param isRecursion 是否递归,true是 false否* @return {"files":["文件地址",""],"dirs":["目录地址",""]}*/public static Map<String, List<String>> getDirFile(String dir, boolean isRecursion) {Map<String, List<String>> map = new HashMap<String, List<String>>();File file = new File(dir);getDirFileDtl(file, map, isRecursion);return map;}
/** 获取目录的指定内容* @param file* @param map*/private static void getDirFileDtl(File file, Map<String, List<String>> map, boolean isRecursion) {File[] t = file.listFiles();if(t == null) {return;}for(int i = 0; i < t.length; i++){//判断文件列表中的对象是否为文件夹对象,如果是则执行tree递归,直到把此文件夹中所有文件输出为止if(t[i].isDirectory()) {List<String> dirs = map.get("dirs");if(dirs == null) {dirs = new ArrayList<String>();}dirs.add(t[i].getAbsolutePath());//System.out.println(t[i].getAbsolutePath()+"\n");map.put("dirs", dirs);if(isRecursion) {getDirFileDtl(t[i], map, isRecursion);}} else{List<String> files = map.get("files");if(files == null) {files = new ArrayList<String>();}files.add(t[i].getAbsolutePath());//System.out.println(t[i].getAbsolutePath()+"\n");map.put("files", files);getDirFileDtl(t[i], map, isRecursion);}}}/*** 读取http地址的文件到指定位置* @param url* @param savePath* @param saveName* @return*/public static File readFile(String url, String savePath, String saveName) {try {//new一个URL对象URL u = new URL(url);//打开链接HttpURLConnection conn = (HttpURLConnection)u.openConnection();//设置请求方式为"GET"conn.setRequestMethod("GET");//超时响应时间为5秒conn.setConnectTimeout(5 * 1000);//通过输入流获取图片数据InputStream inStream = conn.getInputStream();//得到图片的二进制数据,以二进制封装得到数据,具有通用性byte[] data = readFileBytes(inStream);//new一个文件对象用来保存图片,默认保存当前工程根目录createDir(savePath);File file = new File(savePath + saveName);if(file.exists()) {file.delete();}file = new File(savePath + saveName);//创建输出流FileOutputStream outStream = new FileOutputStream(file);//写入数据outStream.write(data);//关闭输出流outStream.close();return file;} catch (IOException e) {LOGGER.error("读取异常", e);}return null;}/*** 创建ZIP文件* @param sourcePath 文件或文件夹路径* @param zipPath 生成的zip文件存在路径(包括文件名)*/public static boolean createZip(String sourcePath, String zipPath) {FileOutputStream fos = null;ZipOutputStream zos = null;try {fos = new FileOutputStream(zipPath);zos = new ZipOutputStream(fos);writeZip(new File(sourcePath), "", zos);} catch (FileNotFoundException e) {LOGGER.error("创建ZIP文件失败", e);return false;} finally {try {if (zos != null) {zos.close();}} catch (IOException e) {LOGGER.error("创建ZIP文件失败",e);}}return true;}
private static void writeZip(File file, String parentPath, ZipOutputStream zos) {if(file.exists()){if(file.isDirectory()){//处理文件夹parentPath+=file.getName()+File.separator;File [] files=file.listFiles();for(File f:files){writeZip(f, parentPath, zos);}}else{FileInputStream fis=null;DataInputStream dis=null;try {fis=new FileInputStream(file);dis=new DataInputStream(new BufferedInputStream(fis));ZipEntry ze = new ZipEntry(parentPath + file.getName());zos.putNextEntry(ze);byte [] content=new byte[1024];int len;while((len=fis.read(content))!=-1){zos.write(content,0,len);zos.flush();}} catch (FileNotFoundException e) {LOGGER.error("创建ZIP文件失败",e);} catch (IOException e) {LOGGER.error("创建ZIP文件失败",e);}finally{try {if(dis!=null){dis.close();}}catch(IOException e) {LOGGER.error("创建ZIP文件失败",e);}}}}}
/*** 公用下载文件<br>* frame 返回路径和文件名称* fileName:下载文件的名称* downloadPath:下载文件的路径* @param request* @param response* @param frame* @throws IOException */public void download(HttpServletRequest request, HttpServletResponse response,String fileName, String downloadPath) throws IOException {response.setContentType("text/html;charset=UTF-8");try {request.setCharacterEncoding("UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}BufferedInputStream bis = null;BufferedOutputStream bos = null;if(FrameStringUtil.isEmpty(fileName) || FrameStringUtil.isEmpty(downloadPath)) {return;}long fileLength = new File(downloadPath).length();response.setHeader("Content-disposition", "attachment; filename=" + new String(fileName.getBytes("utf-8"),"iso-8859-1"));response.setHeader("Content-Length", String.valueOf(fileLength));bis = new BufferedInputStream(new FileInputStream(downloadPath));bos = new BufferedOutputStream(response.getOutputStream());byte[] buff = new byte[2048];int bytesRead;while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {bos.write(buff, 0, bytesRead);}bis.close();bos.close();}
以上的是Excel操作之工具类 若需完整代码 可识别二维码后 给您发代码。