远程xml部分内容
<imagelist name="FY4A AGRI IMG REGI MTCC GLL" tag="FY4A AGRI IMG REGI MTCC GLL">
<image time="2023-07-25 22:30 (UTC)" desc="FY4A AGRI IMG REGI MTCC GLL" url="http://img.nsmc.org.cn/PORTAL/FY4/IMG/FY4A/AGRI/IMG/REGI/MTCC/GLL/FY4A-_AGRI--_N_REGI_1047E_L1C_MTCC_MULT_GLL_20230725223000_20230725223417_1000M_V0001.JPG"/>
<image time="2023-07-25 22:23 (UTC)" desc="FY4A AGRI IMG REGI MTCC GLL" url="http://img.nsmc.org.cn/PORTAL/FY4/IMG/FY4A/AGRI/IMG/REGI/MTCC/GLL/FY4A-_AGRI--_N_REGI_1047E_L1C_MTCC_MULT_GLL_20230725222336_20230725222753_1000M_V0001.JPG"/>
</imagelist>
mq发布端定时任务发送消息
@Component
public class TFYImage {
private ISyncFY syncFY;
Log log = LogFactory.getLog(TFYImage.class);
@Autowired
public TFYImage(ISyncFY syncFY){
this.syncFY = syncFY;
}
@PostConstruct
@Scheduled(cron = "0 0 * * * *")
public void Task1() {
log.info("execute FY Image task");
String xmlUrl = "xml path";
String localPath = "/media/resource/FY4APic/";
String type = "FY4A";
syncFY.syncFY4AImage(xmlUrl, localPath, type);
}
}
mq消费端
1,远程xml读取
2,xml解析,将image中图片url保存在集合中
3,遍历集合,当本地不存在此图片时,下载图片至本地
4,将图片路径传给延时队列,用于稍后删除图片
5,保存自定义图片访问路径等信息到数据库
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.sxqx.entity.MQMessage;
import com.sxqx.listener.IMessageReceiver;
import com.sxqx.mapper.remote.xugu1.fy.IFYImageMapper;
import com.sxqx.pojo.FYImageItem;
import com.sxqx.utils.common.ListUtils;
import com.sxqx.utils.dataConverter.JsonConverter;
import com.sxqx.utils.file.FileHelper;
import com.sxqx.utils.mq.MQMessageSender;
import com.sxqx.utils.xml.XMLUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
@Component
public class SyncFYImgReceiver implements IMessageReceiver {
private final IFYImageMapper fyImageMapper;
private final MQMessageSender mqMessageSender;
@Autowired
public SyncFYImgReceiver(MQMessageSender mqMessageSender,
IFYImageMapper fyImageMapper
) {
this.mqMessageSender = mqMessageSender;
this.fyImageMapper = fyImageMapper;
}
Log log = LogFactory.getLog(SyncFYImgReceiver.class);
@RabbitListener(queuesToDeclare = {
@Queue(name = "sxqxgxw_sync_fy_img")
})
@RabbitHandler
@Override
public void onMessageReceived(String mqMessageString) {
JsonNode jsonNode = JsonConverter.jsonString2JsonNode(mqMessageString);
JsonNode msg = jsonNode.findValue("msg");
JsonNode JsonNodeParams = msg.findValue("params");
Map<String, Object> params = JsonConverter.jsonNode2HashMap(JsonNodeParams);
if (params.size() > 0) {
String xmlUrl = params.get("xmlUrl").toString();
String localPath = params.get("localPath").toString();
String type = params.get("type").toString();
if(Objects.equals(type,"FY4A")){
List<String> imageUrlList = new ArrayList<>();
try {
//读取xml
Document document = XMLUtil.readXMLUrl(xmlUrl);
// 创建一个XPath对象
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
// 使用XPath表达式获取imagelist节点
XPathExpression expr = xPath.compile("/imagelist");
NodeList nodeList = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
// 遍历imagelist节点
Node node = nodeList.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element imagelistElement = (Element) node;
// 获取name和tag属性值
//String name = imagelistElement.getAttribute("name");
//String tag = imagelistElement.getAttribute("tag");
//System.out.println("name: " + name);
//System.out.println("tag: " + tag);
// 获取image节点列表
NodeList imageNodes = imagelistElement.getElementsByTagName("image");
// 遍历image节点
//读取xml中image存入imageUrlList
for (int j = 0; j < imageNodes.getLength(); j++) {
Node imageNode = imageNodes.item(j);
if (imageNode.getNodeType() == Node.ELEMENT_NODE) {
Element imageElement = (Element) imageNode;
// 获取image节点的time、desc和url属性值
//String time = imageElement.getAttribute("time");
//String desc = imageElement.getAttribute("desc");
String imageUrl = imageElement.getAttribute("url");
imageUrlList.add(imageUrl);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
List<FYImageItem> fyImageItems = new ArrayList<>();
//下载图片,组装数据
for (String imageUrl : imageUrlList) {
// 获取最后一个斜杠的位置
int slashIndex = imageUrl.lastIndexOf("/");
// 截取文件名
String fileName = imageUrl.substring(slashIndex + 1);
String filePath = localPath;
String savePath = filePath + fileName;
File file = new File(savePath);
if (file.exists()) {
continue;
}
//下载图片
try {
long start = System.currentTimeMillis();
FileHelper.downloadUsingNIO(imageUrl, savePath);
long end = System.currentTimeMillis();
long timeDifferenceInSeconds = (end - start) / 1000;
log.info(savePath + " 下载耗时:" + timeDifferenceInSeconds + "秒");
} catch (IOException e) {
e.printStackTrace();
}
if (file.exists() && file.length() > 0) {
//组装数据
String[] s = fileName.split("_");
if (s.length == 13) {
try {
String product = s[0].replace("-", "");
String dt = s[9].substring(0, 14);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = sdf.parse(dt);
Calendar bjc = Calendar.getInstance();
bjc.setTime(date);
bjc.add(Calendar.HOUR_OF_DAY, 8);
date = bjc.getTime();
FYImageItem fyImageItem = new FYImageItem();
fyImageItem.setTime(date);
fyImageItem.setPath("http://本地服务器/mediaResource/FY4APic/" + fileName);
fyImageItem.setFilename(fileName);
fyImageItem.setProduct(product);
fyImageItems.add(fyImageItem);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 清除数据
MQMessage mqMessage = new MQMessage();
JSONObject jsonObject = new JSONObject();
jsonObject.put("filePath", savePath);
mqMessage.setMsg(jsonObject);
mqMessageSender.send("queue.file_delay_destroy", mqMessage);
}
//保存到数据库
if (fyImageItems.size() > 0) {
for (List<FYImageItem> fyImageItems1 : ListUtils.splitList(fyImageItems, 50)) {
int rows = fyImageMapper.insertIntoFYImage(fyImageItems1);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
try {
Thread.sleep(100);
} catch (Exception e) {
}
} else {
log.info("don't need to sync fy4a file and fyImageItems.size() is " + fyImageItems.size());
}
}
}
}
}
XMLUtil读取远程xml链接
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.net.HttpURLConnection;
import java.net.URL;
public class XMLUtil {
public static Document readXMLUrl(String xmlUrl) throws Exception{
// 创建一个URL对象
URL url = new URL(xmlUrl);
// 创建一个DocumentBuilderFactory对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 创建一个DocumentBuilder对象
DocumentBuilder builder = factory.newDocumentBuilder();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置连接超时时间为5秒
connection.setConnectTimeout(5000);
// 设置读取超时时间为10秒
connection.setReadTimeout(10000);
// 从URL中读取XML文件并解析
Document document = builder.parse(connection.getInputStream());
return document;
}
}
使用NIO下载文件
package com.sxqx.utils.file;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
public class FileHelper {
public static void deleteFile(File file) {
/*
File[] listFiles()
返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。
*/
File[] files = file.listFiles();
if (files!=null) {//如果包含文件进行删除操作
for (File value : files) {
if (value.isFile()) {
//删除子文件
value.delete();
} else if (value.isDirectory()) {
//通过递归的方法找到子目录的文件
deleteFile(value);
}
value.delete();//删除子目录
}
}
file.delete();
}
public static Boolean downloadFile(String urlString, String savePath) {
InputStream is = null;
FileOutputStream os = null;
try {
// 构造URL
URL url = new URL(urlString);
// 打开连接
URLConnection con = url.openConnection();
// 输入流
is = con.getInputStream();
// 1K的数据缓冲
byte[] bs = new byte[1024];
// 读取到的数据长度
int len;
// 输出的文件流
File file = new File(savePath);
os = new FileOutputStream(file, true);
// 开始读取
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
// 完毕,关闭所有链接
try {
if (null != os) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//从微信下载图片时如果没有id对应的图片则下载一个空图片,不会存在返回为null的情况
}
/**
* 使用NIO下载文件
* @param urlStr
* @param file
* @throws IOException
*/
public static void downloadUsingNIO(String urlStr, String file) throws IOException {
URL url = new URL(urlStr);
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
FileOutputStream fos = new FileOutputStream(file);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}
======================================================================
上传附件到本地路径,并将访问path保存在数据库中
Controller层代码
给方法设置访问权限,将对应权限配置在数据库表中,只允许admin用户访问
/**
* 资料数据上传
* @param file 上传的附件
* @param orderId 申请单id
* @return Result
*/
@PreAuthorize("hasAuthority('user:offline:uploadData')")
@PostMapping(value = "/uploadData")
public Result<Object> uploadData(MultipartFile[] file, String orderId) {
return applyOrderService.uploadData(file, orderId);
}
数据库目录表和角色目录关联表中配置相应方法访问权限
service层代码
//1,springsecurity利用上下文获取用户信息
//2,查询订单是否存在
//3,io流上传附件
//4,将配置nginx后的附件url保存起来
@Override
public Result<Object> uploadData(MultipartFile[] uploadFile, String orderId) {
UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
JWTUser jwtUser = (JWTUser) authentication.getPrincipal();
InputStream inputStream = null;
FileOutputStream fileOutputStream = null;
LambdaQueryWrapper<ApplyOrderDO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ApplyOrderDO::getOrderId, orderId);
ApplyOrderDO applyOrderDO = applyOrderMapper.selectOne(queryWrapper);
if (applyOrderDO == null) return Result.error(new CodeMsg(400, "申请单不存在"));
if (applyOrderDO.getOrderProcessNode()!=OrderProcessNode.PROVIDE_DATA && applyOrderDO.getOrderProcessNode()!=OrderProcessNode.FINISH) {
return Result.error(new CodeMsg(400, "当前申请单状态不能上传附件"));
}
LambdaQueryWrapper<ApplyOrderProcessDO> queryWrapper2 = new LambdaQueryWrapper<>();
queryWrapper2.eq(ApplyOrderProcessDO::getOrderId, orderId);
queryWrapper2.eq(ApplyOrderProcessDO::getProcessId, OrderProcessNode.PROVIDE_DATA);
queryWrapper2.eq(ApplyOrderProcessDO::getProcessResult, "PASS");
applyOrderProcessMapper.delete(queryWrapper2);
String filename;
String ipAddress = "";
List<Map<String, String>> list = new ArrayList<>();
try {
InetAddress localhost = InetAddress.getLocalHost();
ipAddress = localhost.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
try {
for (MultipartFile file : uploadFile) {
filename = file.getOriginalFilename();
System.out.println(filename);
File dir = new File("/data/static/dataSharingStatic/offline/orderFile/" + orderId + "/");
if (!dir.exists()) {
boolean mkdirs = dir.mkdirs();
}
inputStream = file.getInputStream();
fileOutputStream = new FileOutputStream("/data/static/dataSharingStatic/offline/orderFile/" + orderId + "/" + filename);
IOUtils.copy(inputStream, fileOutputStream);
fileOutputStream.flush();
Map<String, String> map = new HashMap<>();
map.put("filename", filename);
map.put("filePath", "http://"+ipAddress+"/dataSharingStatic/offline/orderFile/"+ orderId +"/"+filename);
list.add(map);
}
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
list.forEach(map-> {
ApplyOrderProcessDO processDetail = new ApplyOrderProcessDO();
processDetail.setOrderId(orderId);
// 这里的是正在进行中的流程,而不是执行完后显示下一步流程。
processDetail.setProcessId(OrderProcessNode.PROVIDE_DATA);
processDetail.setProcessResult("PASS");
processDetail.setProcessRemarks("数据已上传,申请完成");
processDetail.setProcessTime(new Date());
processDetail.setProcessDealUser(jwtUser.getUserDO().getUsername());
processDetail.setProcessDealMobile(jwtUser.getUserDO().getMobile());
processDetail.setProcessAppendixUrl(map.get("filePath"));
processDetail.setProcessAppendixRemarks(map.get("filename"));
applyOrderProcessMapper.insert(processDetail);
});
applyOrderDO.setUpdateTime(new Date());
applyOrderDO.setUpdateUserId(jwtUser.getUserDO().getUuid());
applyOrderDO.setUpdateUserName(jwtUser.getUserDO().getUsername());
applyOrderDO.setUpdateDealMobile(jwtUser.getUserDO().getMobile());
applyOrderDO.setOrderStatus(OrderConstant.APPLIED);
applyOrderDO.setDealStatus(DealStatus.PROCESSED);
applyOrderDO.setOrderProcessNode(OrderProcessNode.FINISH);
applyOrderDO.setModifiedUserRealName(jwtUser.getUserDO().getUserRealName());
applyOrderDO.setModifiedUserNackName(jwtUser.getUserDO().getNickName());
applyOrderDO.setRemarks("数据已上传,申请完成");
int update = applyOrderMapper.update(applyOrderDO, queryWrapper);
if (update > 0) {
return Result.success("上传附件成功");
}
return Result.error(new CodeMsg(500, "上传附件失败"));
}
postman触发上传附件请求
配置文件配置文件大小限制
spring:
servlet:
multipart:
max-file-size: 300MB
max-request-size: 300MB
全局异常处理类捕获文件大小超出限制异常返回给前端文章来源:https://www.toymoban.com/news/detail-609797.html
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Result<?> handleException(Exception e) throws Exception {
if (e instanceof AccessDeniedException) {
throw e;
}
if (e instanceof HttpRequestMethodNotSupportedException) {
return Result.error(new CodeMsg(5052, e.getMessage()));
}
if (e instanceof ServiceException) {
return Result.error(new CodeMsg(5052, e.getMessage()));
}
if (e instanceof HttpMessageNotReadableException) {
return Result.error(new CodeMsg(5053, "参数无法识别!请检查参数"));
}
if (e instanceof MissingServletRequestParameterException) {
return Result.error(CodeMsg.CONTROL_ERROR);
}
if (e instanceof MaxUploadSizeExceededException) {
return Result.error(new CodeMsg(5054, "文件总大小不能超过300MB"));
}
e.printStackTrace();
return Result.error(CodeMsg.SERVER_ERROR);
}
}
nginx配置静态资源访问路径文章来源地址https://www.toymoban.com/news/detail-609797.html
server {
listen 80;
server_name 123.123.123.123;
add_header Cache-Control no-store;
charset utf-8;
location / {
root /mnt/sxqxgxw-gzb-front/dist/;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
#访问/dataSharingStatic时,相当于访问/data/static/dataSharingStatic路径下资源
location /dataSharingStatic {
root /data/static;
autoindex on;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requestd-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /api/ {
proxy_pass http://123.123.123.123:8896;
rewrite ^/api/(.*)$ /$1 break;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requestd-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS;
}
}
到了这里,关于远程xml读取解析,将image url下载到本地,延时队列定时删除文件,图片访问路径保存在数据库中的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!