Browse Source

增加电子回单FTP访问

wangjun 14 hours ago
parent
commit
2084c1723d

+ 353 - 0
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/AttachmentFileUtil.java

@@ -0,0 +1,353 @@
+package nckd.jimin.jyyy.fi.webapi;
+
+import kd.bos.cache.CacheFactory;
+import kd.bos.cache.TempFileCache;
+import kd.bos.context.RequestContext;
+import kd.bos.entity.MainEntityType;
+import kd.bos.fileservice.FileItem;
+import kd.bos.fileservice.FileService;
+import kd.bos.fileservice.FileServiceFactory;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.AttachmentServiceHelper;
+import kd.bos.servicehelper.MetadataServiceHelper;
+import kd.bos.util.FileNameUtils;
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPReply;
+import nckd.jimin.jyyy.bd.common;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.text.DecimalFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author lxl
+ */
+public class AttachmentFileUtil {
+
+    private final static Log logger = LogFactory.getLog(AttachmentFileUtil.class);
+    /**
+     * @param entity 目标单据实体标识
+     * @param pk 目标数据id
+     * @param fileUrl 待存入文件的url
+     * @param fileName 带存入文件名称
+     * @param fileSize 带存入文件大小
+     * @param attachKey 附件面板标识
+     * @throws IOException
+     * 温馨提示:如果不在attachItem对象中添加uid这个属性,会出现上传多个附件,但是最终跟单据绑定的都是第一个附件。
+     */
+    public static Map<String, Object> saveUrlFile2Attchment(String uid1,String entity, Object pk, String fileUrl, String fileName,String fileSize, String attachKey){
+        List<Map<String, Object>> attachments = new ArrayList<>();
+        Map<String, Object> attachItem = new HashMap<>();
+        Map<String, Object> result = new HashMap<>();
+        attachItem.put("name", fileName);
+        attachItem.put("uid", uid1);
+        InputStream inputStream = null;
+        ByteArrayOutputStream outStream = null;
+        HttpURLConnection conn = null;
+        String tempUrl = null;
+        int size = 0;
+        FTPClient ftpClient = null;
+        try {
+            ftpClient = new FTPClient();
+            // 连接到FTP服务器
+            Map<String, String> conf = CommonHelperUtils.getCommonParams("ftp");
+            ftpClient.connect(conf.get("IP"), Integer.parseInt(conf.get("PORT")));
+            ftpClient.login(conf.get("USER"), conf.get("PASSWD"));
+            if(!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){
+                ftpClient.disconnect();
+                return null;
+            }
+
+            // 设置文件类型为二进制
+            ftpClient.type(FTP.BINARY_FILE_TYPE);
+            ftpClient.enterLocalPassiveMode();  // 切换到被动模式
+            fileUrl = encode(fileUrl,"UTF-8");
+            logger.info("fileUrl:" + fileUrl);
+            String dir = ftpClient.printWorkingDirectory();
+            System.out.println(dir);
+            //ftpClient.changeWorkingDirectory("Files/CMB");
+            System.out.println(ftpClient.printWorkingDirectory());
+            //fileUrl = dir + fileUrl;
+
+            inputStream = ftpClient.retrieveFileStream(fileUrl);
+            logger.info("inputStream -- size:"+inputStream.available());
+            System.out.println("inputStream:"+inputStream);
+
+            outStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int len = 0;
+            while( (len = inputStream.read(buffer)) != -1 ){
+                outStream.write(buffer, 0, len);
+            }
+            byte[] bt =  outStream.toByteArray();
+
+            if(null != bt && bt.length > 0){
+                DecimalFormat df = new DecimalFormat("#");
+                size = Integer.parseInt(df.format((double) bt.length));
+
+                System.out.println("文件大小=:" + size);
+            }else{
+                System.out.println("没有从该连接获得内容");
+            }
+
+            attachItem.put("size",  size);
+//            苍穹自带
+            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
+            tempUrl = cache.saveAsFullUrl((String) attachItem.get("name"), inputStream, 1600);
+            logger.info("tempUrl -- inputStream -- size:" + CacheFactory.getCommonCacheFactory().getTempFileCache().getInputStream(tempUrl).available());
+            System.out.println(":tempUrl"+tempUrl);
+        } catch (Exception e) {
+            logger.info("附件上传失败,堆栈信息:",e);
+            result.put("isSuccess", "false");
+            result.put("msg", "转文件流异常"+e);
+            return result;
+        } finally {
+            try {
+                if(inputStream!=null){
+                    inputStream.close();
+                }
+                if(outStream !=null){
+                    outStream.close();
+                }
+                if (ftpClient.isConnected()) {
+                    ftpClient.logout();
+                    ftpClient.disconnect();
+                }
+            } catch (Exception e) {
+                logger.info("附件上传失败,堆栈信息01:",e.getMessage());
+                result.put("isSuccess", "false");
+                result.put("msg", "文件流关闭异常:"+e.getMessage());
+                return result;
+            }
+        }
+        try{
+            attachItem.put("lastModified",System.currentTimeMillis());
+            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
+            String appId = dataEntityType.getAppId();
+
+            //上传到临时文件服务器
+            String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity, pk, (String)attachItem.get("name"));
+            logger.info("actUrl:"+actUrl);
+            System.out.println("actUrl:"+actUrl);
+            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
+            InputStream in = cache.getInputStream(tempUrl);
+            FileService service = FileServiceFactory.getAttachmentFileService();
+            RequestContext requestContext = RequestContext.get();
+            String uuid = UUID.randomUUID().toString().replace("-", "");
+            String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
+                    requestContext.getAccountId(), uuid, fileName);
+            System.out.println("pathParam"+pathParam);
+
+            result.put("pathParam", pathParam);
+            FileItem fileItem = new FileItem(fileName, pathParam, in);
+
+            //从临时上传至 文件服务器
+            String downUrl =service.upload(fileItem);
+            logger.info("downUrl:"+downUrl);
+            System.out.println("downUrl:"+downUrl);
+
+            attachItem.put("url", actUrl);
+            attachments.add(attachItem);
+            //绑定单据
+            AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
+
+        }catch(Exception e1){
+            logger.info("附件上传失败,堆栈信息e1:",e1);
+            result.put("isSuccess", "false");
+            result.put("msg", "上传服务器异常:"+e1);
+            return result;
+        }finally {
+
+        }
+        result.put("isSuccess", "true");
+        result.put("msg", "附件上传成功");
+        return result;
+    }
+
+    public static String ioPost(String tempUrl,String fileName,String entity,String size,String attachKey,Object pk){
+        List<Map<String, Object>> attachments = new ArrayList<>();
+        Map<String, Object> attachItem = new HashMap<>();
+        try{
+            MainEntityType dataEntityType = MetadataServiceHelper.getDataEntityType(entity);
+            String appId = dataEntityType.getAppId();
+
+            //上传到临时文件服务器
+            System.out.println(tempUrl);
+            String actUrl = AttachmentServiceHelper.saveTempToFileService(tempUrl,appId,entity, pk,fileName);
+            System.out.println("actUrl:"+actUrl);
+            TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();
+            InputStream in = cache.getInputStream(tempUrl);
+            FileService service = FileServiceFactory.getAttachmentFileService();
+            RequestContext requestContext = RequestContext.get();
+            String uuid = UUID.randomUUID().toString().replace("-", "");
+            String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(),
+                    requestContext.getAccountId(), uuid, fileName);
+            System.out.println("pathParam:"+pathParam);
+            FileItem fileItem = new FileItem(fileName, pathParam, in);
+
+            //从临时上传至 文件服务器
+            String downUrl =service.upload(fileItem);
+            System.out.println("downUrl:"+downUrl);
+
+            attachItem.put("name", fileName);
+            attachItem.put("size", size);
+            attachItem.put("lastModified",System.currentTimeMillis());
+            attachItem.put("url", actUrl);
+
+            attachments.add(attachItem);
+            //        绑定单据
+            AttachmentServiceHelper.upload(entity, pk, attachKey, attachments);
+        }catch (Exception e){
+            System.out.println(e);
+            return e.toString();
+        }
+        return "ss";
+    }
+
+    /**
+     * 根据地址获得数据的字节流并转换成大小
+     * @param strUrl 网络连接地址
+     * @return
+     */
+    public static int getFileSizeByUrl(String strUrl){
+        InputStream inStream=null;
+        ByteArrayOutputStream outStream=null;
+        int size = 0;
+        try {
+            URL url = new URL(strUrl);
+            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+            conn.setRequestMethod("GET");
+            conn.setConnectTimeout(5 * 1000);
+            inStream = conn.getInputStream();
+
+            outStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int len = 0;
+            while( (len=inStream.read(buffer)) != -1 ){
+                outStream.write(buffer, 0, len);
+            }
+            byte[] bt =  outStream.toByteArray();
+
+            if(null != bt && bt.length > 0){
+                DecimalFormat df = new DecimalFormat("#");
+                size = Integer.parseInt(df.format((double) bt.length));
+
+                System.out.println("文件大小=:" + size);
+            }else{
+                System.out.println("没有从该连接获得内容");
+            }
+            inStream.close();
+            outStream.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }finally{
+            try{
+                if(inStream !=null){
+                    inStream.close();
+                }
+                if(outStream !=null){
+                    outStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return size;
+    }
+
+    private static InputStream getInputStreamFromURL(String urlString) throws IOException {
+        URL url = null;
+        try {
+            url = new URL(urlString);
+            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
+            //设置超时间为3秒
+            conn.setConnectTimeout(3*1000);
+            //防止屏蔽程序抓取而返回403错误
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            //得到输入流
+            return conn.getInputStream();
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+        return null;
+    }
+
+    /**
+     * 处理url里的中文
+     * @param url
+     * @return
+     */
+    private static String zhPattern = "[\\u4e00-\\u9fa5]";
+
+    /**
+     * 替换字符串卷
+     *
+     * @param str 被替换的字符串
+     * @param charset 字符集
+     * @return 替换好的
+     * @throws UnsupportedEncodingException 不支持的字符集
+     */
+    public static String encode(String str, String charset) throws UnsupportedEncodingException {
+        Pattern p = Pattern.compile(zhPattern);
+        Matcher m = p.matcher(str);
+        StringBuffer b = new StringBuffer();
+        while (m.find()) {
+            m.appendReplacement(b, URLEncoder.encode(m.group(0), charset));
+        }
+        m.appendTail(b);
+        return b.toString();
+    }
+
+    public static void downloadFile(String fileUrl, String saveDir) throws IOException {
+        URL url = new URL(fileUrl);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestMethod("GET");
+
+        int responseCode = connection.getResponseCode();
+        if (responseCode == HttpURLConnection.HTTP_OK) {
+            String fileName = "";
+            String disposition = connection.getHeaderField("Content-Disposition");
+            String contentType = connection.getContentType();
+
+            if (disposition != null) {
+                int index = disposition.indexOf("filename=");
+                if (index > 0) {
+                    fileName = disposition.substring(index + 10, disposition.length() - 1);
+                }
+            } else { fileUrl= URLDecoder.decode(fileUrl);//前面中文encode了,这里decode才能保持原文件名
+                fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
+            }
+
+            InputStream inputStream = connection.getInputStream();
+            File saveFile=new File(saveDir);
+            if(!saveFile.exists()){
+                saveFile.mkdirs();
+            }
+            String saveFilePath = saveDir + File.separator + fileName;
+
+            FileOutputStream outputStream = new FileOutputStream(saveFilePath);
+
+            int bytesRead;
+            byte[] buffer = new byte[1024];
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+
+            outputStream.close();
+            inputStream.close();
+            System.out.println(saveDir+"文件下载完成");
+        } else {
+            System.out.println("文件下载失败,错误码:" + responseCode+";错误文件为"+saveDir);
+        }
+        connection.disconnect();
+    }
+
+}

+ 43 - 15
code/jyyy/nckd-jimin-jyyy-fi/src/main/java/nckd/jimin/jyyy/fi/webapi/TransDetailApiPlugin.java

@@ -2,6 +2,7 @@ package nckd.jimin.jyyy.fi.webapi;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import kd.bos.config.client.util.StringUtils;
 import kd.bos.dataentity.entity.DynamicObject;
 import kd.bos.dataentity.entity.DynamicObjectCollection;
 import kd.bos.db.DB;
@@ -19,10 +20,11 @@ import kd.bos.orm.query.QFilter;
 import kd.bos.servicehelper.BusinessDataServiceHelper;
 import kd.bos.servicehelper.operation.DeleteServiceHelper;
 import kd.bos.servicehelper.operation.SaveServiceHelper;
+
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Date;
-import nckd.jimin.jyyy.fi.webapi.BeiTransdetailConstantInfo;
+import java.util.Map;
 
 
 /**
@@ -273,6 +275,9 @@ public class TransDetailApiPlugin implements Serializable {
                 errMsg.append("业务类型不存在;");
                 break;
         }
+        if(EmptyUtils.isNotEmpty(errMsg)){
+            return errMsg.toString();
+        }
 
         String electricAddress = jsonObject.getString("electricAddress");
         // 判断是否有电子回单,如果有则处理电子回单单据对象,并保存
@@ -284,6 +289,7 @@ public class TransDetailApiPlugin implements Serializable {
             String errStr = saveElecreceipt(transDetail, elecreceipt,electricAddress);
             if (EmptyUtils.isNotEmpty(errStr)) {
                 errMsg.append(errStr);
+                return errMsg.toString();
             }else{
                 transDetail.set(BeiTransdetailConstantInfo.ISMATCHERECEIPT, true); // 是否匹配电子回单
 
@@ -302,6 +308,7 @@ public class TransDetailApiPlugin implements Serializable {
         StringBuilder errMsg = new StringBuilder();
 
         DynamicObject elecreceiptDyn = null;
+        String receiptNo = transDetail.getString(BeiTransdetailConstantInfo.RECEIPTNO);
         if(!EmptyUtils.isEmpty(elecreceipt)){
             elecreceiptDyn = elecreceipt;
         }else {
@@ -343,7 +350,7 @@ public class TransDetailApiPlugin implements Serializable {
             if(entrys1.size()<=0) {
                 DynamicObject entry1 = entrys1.addNew();
                 entry1.set("e_receiptid", Id);
-                entry1.set("e_receiptno", transDetail.get(BeiTransdetailConstantInfo.RECEIPTNO));
+                entry1.set("e_receiptno", receiptNo);
             }
 
         }
@@ -352,27 +359,48 @@ public class TransDetailApiPlugin implements Serializable {
          * 地址格式:address="ftp:\\\\172.16.3.232\\Files\\12Qwee.pdf";
          * 格式 :ftp://172.16.68.44:21/Files/CMB//791904936510302_20250422-20250422_365B261684797_C04474R0007ZOYZ.jpg
          */
-        String address = electricAddress;
-        String filename = extractFilename(address);
-        elecreceiptDyn.set(BeiElecreceiptConstantInfo.UPLOADFILENAME,filename);//文件名称
+        if(EmptyUtils.isNotEmpty(electricAddress)){
+            String address = electricAddress;
+            String filename = extractFilename(address);
+            elecreceiptDyn.set(BeiElecreceiptConstantInfo.UPLOADFILENAME,filename);//文件名称
 
-        address=address.split("Files")[1];
-        address=address.replace("\\", "/");
-        address="/Files"+address;
-        address=address.replace("//", "/");
-        elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEPATH,address);//电子回单路径
+            address=address.split("Files")[1];
+            address=address.replace("\\", "/");
+            address="/Files"+address;
+            address=address.replace("//", "/");
+            elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEPATH,address);//电子回单路径
 
-        /**
-         * 处理文件上传
-         */
-
-        elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEFLAG, "1"); // 是否已上传
+            /**
+             * 从FTP上将文件上传到苍穹中,处理文件上传
+             */
+            String fileurl =  oprationFilename(address);
+            Map<String, Object> reMap = AttachmentFileUtil.saveUrlFile2Attchment(receiptNo, BeiElecreceiptConstantInfo.ENTITYID, elecreceiptDyn.getPkValue(), fileurl, filename, "0", "attachmentpanel");
+            if(reMap.get("isSuccess").toString().equals("false")){
+                errMsg.append(reMap.get("msg").toString());
+                return errMsg.toString();
+            }else{
+                String pathParam = reMap.get("pathParam").toString();
+                if(StringUtils.isNotEmpty(pathParam)){
+                    elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEPATH, pathParam);
+                }
+            }
+            elecreceiptDyn.set(BeiElecreceiptConstantInfo.FILEFLAG, "1"); // 是否已上传
+        }
 
         SaveServiceHelper.save(new DynamicObject[]{elecreceiptDyn});
 
         return errMsg.toString();
     }
 
+    public static String oprationFilename(String path) {
+        // Remove the leading slash if present
+        if (path.startsWith("/")) {
+            path = path.substring(1);
+        }
+        // Extract the substring after the last slash
+        return path;
+    }
+
     public static String extractFilename(String address) {
         // Find the last slash in the URL
         int lastSlashIndex = address.lastIndexOf('/');