业务背景
公司的技术图纸文档全部保存在文件服务器某个文件夹中,通过AD域自动映射网络驱动器到用户PC上。随着公司多年数据积累越来走多,用户在该目录下,使用Windows搜索功能找出任务单需要的技术图纸越来越慢。为了提高用户打印技术图纸的效率,开发一个技术图纸管理功能,让用户上传技术图纸或者维护技术图本地路径对应的物料编码,然后用户只要输入任务单就可以查找出技术图纸批量打印。
另外,公司的技术图纸命名前缀都是用物料编码,因此,上传文件或读取文件信息时,可以自动把物料编码与技术图纸文件名建立对应关系,减少用于对基础数据的维护工作量。
Oracle EBS环境
1. Oracle EBS 版本:Oracle 应用产品 : 11.5.10.2
2. Oracle EBS 的Java版本: 1.4.2_04,其查方法如下
[appldev@gbdev ~]$ java -version
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)
前提条件
1.FTP必须java组件:commons-net-1.4.1,最好找到与Oracle EBS Java的版兼容。
2.Java开发工具:Eclipse需求要引用相关jar文件:f60all.jar,或者Oracle9i JDeveloper(无需引用form相关的jar文件)
JavaBean源代码
package oracle.forms.fd;
import oracle.forms.api.FException;
import oracle.forms.properties.ID;
import oracle.forms.ui.CustomEvent;
import oracle.forms.ui.VBean;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
//import java.io.UnsupportedEncodingException;
import java.io.OutputStream;
import java.io.FileOutputStream;
import java.net.SocketException;
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
public class OperatorFile extends VBean{
//private static String LOCAL_CHARSET = "GBK"; //本地字符编码
//private static String SERVER_CHARSET = "ISO-8859-1";//FTP协议里面,规定文件名编码为iso-8859-1
public static final String RCS_ID = "$Header: OperatorFile.java 1.0 2007/01/25 20:00:00 Alan.Chen$";
//FTP相关参数
static final ID FTPHOST =ID.registerProperty("FTPHOST"); //Ftp服务器IP地址或Url
static final ID PORT = ID.registerProperty("PORT"); //端口
static final ID USERNAME =ID.registerProperty("USERNAME"); //FTP服务器登陆用户
static final ID PASSWORD = ID.registerProperty("PASSWORD"); //FTP服务器登陆用户密码
private static String ftpHost="";
private static int port=21;
private static String userName=null;
private static String password=null;
//批量上传文件或读取文件信息
static final ID LOCALFILE = ID.registerProperty("LOCALFILE");//本地文件(包括绝对路径)
static final ID FTPUPLOAD= ID.registerProperty("FTPUPLOAD");//FTP 上传文件目录
private static String localFile=null; //客户端文件(包含绝对路径)
private static String ftpUploadPath = "";
private int fileTotal=0;
private String fileId= null;
private String fileSuffix=null;
static final ID FILEINDEX = ID.registerProperty("FILEINDEX");//java批量读取文件数组的索引
//来源于CUX.CUX_WIP_MFGDRAW_S.NEXTVAL,用于转换文件名称,防止中文文件名乱码问题
static final ID FILEID =ID.registerProperty("FILEID");
static final ID FILETOTAL = ID.registerProperty("FILETOTAL");//文件总数量
static final ID FILENAME = ID.registerProperty("FILENAME");//文件名称
static final ID FILESUFFIX = ID.registerProperty("FILESUFFIX");//文件后缀(文件类型)
private File[] files= null;
private int fileIndex=0;
static final ID ERRORMESSAGE = ID.registerProperty("ERRORMESSAGE");//错误信息
static final ID UPLOADFLAG = ID.registerProperty("UPLOADFLAG"); //上传是否成功
static final ID PRINTFILE = ID.registerProperty("PRINTFILE");//打印文件(包括绝对路径)
static final ID OPENFILE = ID.registerProperty("OPENFILE");//打开文件(包括绝对路径)
static final ID FTPDOWNLOAD= ID.registerProperty("FTPDOWNLOAD"); //下载服务器文件
static final ID DOWNLOADFILE = ID.registerProperty("DOWNLOADFILE");//FTP下载文件名称
static final ID FTPDOWNLOADPATH = ID.registerProperty("FTPDOWNLOADPATH");//FTP下载文件夹
static final ID LOCALFILENAME = ID.registerProperty("LOCALFILENAME");//本地文件名称
static final ID SUCCESS = ID.registerProperty("SUCCESS");//是否成功
static final ID FTPCLOSE = ID.registerProperty("FTPCLOSE");//注销FTP登陆用和断开连接
static final ID FTPDELETE = ID.registerProperty("FTPDELETE");//FTP删除文件
private FileInputStream input=null;
private String fileName=null;
private String localFileName=null;
private String serverFileName=null;
private static FTPClient ftpClient=null; //Ftp
private static String localPath=null; //FTP下载文件至本地路径
private static String ftpDownloadPath=null;
private static String result = "";
public boolean setProperty(ID id, Object value){
boolean result = true;
try {
if(id==FTPHOST){ //设置FTP地址或IP
ftpHost = value.toString();
}else if(id==PORT){ //设置FTP端口默认值21
port = Integer.parseInt(value.toString());
}else if(id==USERNAME){ //FTP登陆用户
userName = value.toString();
}else if(id==PASSWORD){ //FTP登陆密码
password = value.toString();
}else if(id==OPENFILE){ //打开文件
OpenFile_Event(value.toString());
}else if(id==PRINTFILE){ //打印文件
PrintFile_Event(value.toString());
}else if(id==FTPUPLOAD){ //选择要FTP上传或读取文件
if(value.toString().trim()=="false"){
ftpUploadPath = "";
}else{
ftpUploadPath = value.toString().trim();
}
FtpUpload_Event(ftpUploadPath);
}else if(id==FILEINDEX){ //读取文件信息
this.fileIndex = Integer.parseInt(value.toString());
FileIndex_Event(this.fileIndex);
}else if(id==FILEID){ //FTP上传文件
fileId = value.toString();
FileID_Event(fileId);
}else if(id==FTPDOWNLOADPATH){
ftpDownloadPath = value.toString();
}else if(id==LOCALFILENAME){
this.localFileName = value.toString();
}else if(id==DOWNLOADFILE){
this.serverFileName = value.toString();
FtpDownloadFile_Event(this.serverFileName);
}else if(id==FTPDELETE){
}else{
return super.setProperty(id, value);
}
} catch (FException e){
return false;
}
return result;
}
public Object getProperty(ID id){
Object object = "";
if(id==FTPDOWNLOAD){ //FTP下载文件,选择下载保存的本地文件夹
localPath="";
try {
FtpDownload_Event();
} catch (FException e) {
e.printStackTrace();
}
object = localPath;
}else if(id==FTPCLOSE){
object =FtpClose();
}else if(id==FTPUPLOAD){
object =ftpUploadPath;
}else{
object = super.getProperty(id);
}
return object;
}
/**打开本地文件
* @param filePath 本地文件(绝对)路径
* @throws FException
* */
public void OpenFile_Event(String filePath) throws FException{
String result="";
File file = new File(filePath);
if(file.exists()){
try{
Runtime.getRuntime().exec("cmd /c start \" \" \""+ filePath);
result = "文件:"+filePath+"打开成功";
}catch(IOException e){
result ="文件:"+filePath+"打开失败!";
}
}else{
result = "文件:"+filePath+"未找到,请检查文件是否存在!";
}
/**OPENFILE属性赋值时触发自定义事件
* this.getHandler 获得事件管理句柄
* OPENFILE 是声明给属性值OPENFILE赋值时触发事件
*/
CustomEvent ce = new CustomEvent(this.getHandler(), OPENFILE);
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息
this.dispatchCustomEvent(ce);
}
/**打印文件
* @param filePath 文件(绝对)路径
* @throws FException
* */
public void PrintFile_Event(String filePath) throws FException{
String result="";
//DocFlavor dof = null;
//pdf文件打印,非pdf文件打开。
if(filePath.endsWith("pdf")){
try{
Runtime.getRuntime().exec("cmd.exe /C start acrord32 /P /h "+filePath);
result = "文件:"+filePath+"打印成功!";
}catch(Exception e){
result = "文件:"+filePath+"打印失败!";
}
/*}else if(filePath.endsWith("gif")){
dof = DocFlavor.INPUT_STREAM.GIF;
}else if(filePath.endsWith("jpg")){
dof = DocFlavor.INPUT_STREAM.JPEG;
}else if(filePath.endsWith("png")){
dof = DocFlavor.INPUT_STREAM.PNG;*/
}else{
OpenFile_Event(filePath);
return;
}
/*try{
PrintService ps = PrintServiceLookup.lookupDefaultPrintService();
//打印属性
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
pras.add(OrientationRequested.PORTRAIT);
pras.add(new Copies(1));
pras.add(PrintQuality.HIGH);
pras.add(Chromaticity.MONOCHROME);
//文档属性
DocAttributeSet das = new HashDocAttributeSet();
FileInputStream fin = new FileInputStream(filePath);
// 设置打印纸张的大小(以毫米为单位)
das.add(new MediaPrintableArea(0, 0, 210, 296, MediaPrintableArea.MM));
Doc doc = new SimpleDoc(fin, dof, das);
DocPrintJob job = ps.createPrintJob();
job.print(doc, pras);
fin.close();
}catch (IOException e){
result= e.getMessage();
}catch (PrintException pe) {
result= pe.getMessage();
}*/
CustomEvent ce = new CustomEvent(this.getHandler(), PRINTFILE);
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息
this.dispatchCustomEvent(ce);
}
/**创建ftpClient对象
*@param ftpHost FTP服务器的IP或地址
*@param ftpPort 端口
*@param ftpUserName 登陆FTP服务器用户名
*@param password FTP用户的密码
* @throws FException
**/
public static boolean createFTPClient(){
boolean success = false;
ftpClient = new FTPClient();
try{
int reply;
//如果采用默认端口,可以使用ftp.connect(ftpClient)的方式直接连接FTP服务器
ftpClient.connect(ftpHost, port);//连接FTP服务器
ftpClient.login(userName, password);//登录
//ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
reply = ftpClient.getReplyCode();
//检验是否连接成功
if (!FTPReply.isPositiveCompletion(reply)) {
result = "未连接到FTP,用户名或密码错误!";
ftpClient.disconnect();
}else{
result = "FTP连接成功!";
success=true;
}
}catch(SocketException e){
result="FTP的IP地址可能错误,请正确配置!"+e.getMessage();
}catch(IOException e){
result="FTP的端口错误,请正确配置!"+e.getMessage();
}
return success;
}
/**FTP上传文件
*@param ftpPath FTP Server上传文件存在的路径
*@param fileName 文件名
*@param input 上传文件流
* */
public boolean uploadFile(String fileName){
boolean success = true;
try {
ftpClient.changeWorkingDirectory(ftpUploadPath);
//设置上传文件的类型为二进制类型
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.storeFile(fileName, this.input);
this.input.close();
} catch (IOException e) {
success =false;
result="上传文件失败!";
}
return success;
}
/**FTP上传文件触发事件FTPUPLOAD
* @param ftpUploadPath 上传到FTP服务器的文件夹
* @throws FException
* */
public void FtpUpload_Event(String ftpUploadPath) throws FException{
boolean success = true;
result = "";
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
jfc.setMultiSelectionEnabled(true);
int opt = jfc.showDialog(new JLabel(), "Select Files");
if(opt==JFileChooser.APPROVE_OPTION){
files=jfc.getSelectedFiles();
fileTotal = files.length;
if(ftpUploadPath.trim().length()>0){
success = createFTPClient();//创建ftpClient对象
}
//自定义事件
CustomEvent ce = new CustomEvent(this.getHandler(), FTPUPLOAD);
this.getHandler().setProperty(SUCCESS,""+success); //创建ftpClient对象是否成功
this.getHandler().setProperty(ERRORMESSAGE,result);
this.getHandler().setProperty(FILETOTAL,""+fileTotal);//设置操作文件的总个数
dispatchCustomEvent(ce);
}
}
/**读取文件信息触发事件FILEINDEX
* @param fileIndex 文件索引
* */
public void FileIndex_Event(int fileIndex) throws FException{
try {
//new String(files[fileIndex].getAbsolutePath().getBytes(LOCAL_CHARSET),SERVER_CHARSET);
//fileName = new String(files[fileIndex].getName().getBytes(LOCAL_CHARSET),SERVER_CHARSET);
localFile = files[fileIndex].getAbsolutePath();
this.fileName = files[fileIndex].getName();
this.fileSuffix = fileName.substring(fileName.lastIndexOf("."));
//FTP上传路径为空,则表示读取文件信息
if(ftpUploadPath.trim().length()>0){
this.input=new FileInputStream(files[fileIndex]);
}
CustomEvent ce = new CustomEvent(this.getHandler(), FILEINDEX);
this.getHandler().setProperty(LOCALFILE,localFile);//设置客户端文件(包含绝对路径)
this.getHandler().setProperty(FILENAME, this.fileName);//设置文件名称
this.getHandler().setProperty(FILESUFFIX,this.fileSuffix);//设置文件后缀
this.getHandler().setProperty(ERRORMESSAGE,"");//设置错误信息
dispatchCustomEvent(ce);
} catch (FileNotFoundException e) {
CustomEvent ce = new CustomEvent(this.getHandler(), FILEINDEX);
this.getHandler().setProperty(ERRORMESSAGE,e.getMessage());//设置错误信息
dispatchCustomEvent(ce);
} catch (IOException e) {
CustomEvent ce = new CustomEvent(this.getHandler(), FILEINDEX);
this.getHandler().setProperty(ERRORMESSAGE,e.getMessage());//设置错误信息
dispatchCustomEvent(ce);
}
}
/**@FTP上传文件把客户端文件名转换为数据库指定的文件名
* @param fileID 文件名,来源于CUX.CUX_WIP_MFGDRAW_S.NEXTVAL,用于转换文件名称,防止中文文件名乱码问题
* */
public void FileID_Event(String fileID) throws FException{
result = "";
boolean success = false;
String fileNewName = fileId + this.fileSuffix;
success = uploadFile(fileNewName);
CustomEvent ce = new CustomEvent(this.getHandler(), FILEID);
this.getHandler().setProperty(LOCALFILE,localFile);//设置客户端文件
this.getHandler().setProperty(SUCCESS,""+success); //创建ftpClient对象是否成功
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息
dispatchCustomEvent(ce);
}
/**FTP下载文件
*@param ftpPath FTP服务文件夹目录
*@param localPath 本地文件夹目录
*@param serverFileName FTP服务端文件名称
*@param localFileName 本地文件名
* @throws IOException
* */
public boolean downloadFile(String serverFileName){
boolean success=true;
ftpClient.enterLocalPassiveMode();
try {
ftpClient.changeWorkingDirectory(ftpDownloadPath);
File file = new File(localPath + File.separatorChar + localFileName);
OutputStream output = new FileOutputStream(file);
ftpClient.retrieveFile(serverFileName, output);
output.close();
result ="文件:"+serverFileName+",下载成功!";
} catch (IOException e) {
success =false;
result = "文件:"+serverFileName+",下载失败!";
}
return success;
}
/**FTP下载文件创建ftpClient对象和选择保存本地文件夹
* */
public void FtpDownload_Event() throws FException{
boolean success=false;
result = "";
JFileChooser jfc=new JFileChooser();
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int opt = jfc.showDialog(new JLabel(), "Save");
if(opt==JFileChooser.APPROVE_OPTION){
localPath = jfc.getSelectedFile().getPath();
//创建ftpClient对象
success = createFTPClient();//创建ftpClient对象
CustomEvent ce = new CustomEvent(this.getHandler(), FTPDOWNLOAD);
this.getHandler().setProperty(SUCCESS,""+success); //创建ftpClient对象是否成功
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息
dispatchCustomEvent(ce);
}
}
/**FTP下载文件触发事件DOWNLOADFILE
* */
public void FtpDownloadFile_Event(String serverFileName) throws FException{
boolean success=true;
result ="";
success=downloadFile(serverFileName);
CustomEvent ce = new CustomEvent(this.getHandler(), DOWNLOADFILE);
this.getHandler().setProperty(SUCCESS,""+success);//下载文件是否成功
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息
dispatchCustomEvent(ce);
}
/**/
public String FtpClose(){
String result="";
try {
ftpClient.logout();
ftpClient.disconnect();
result ="FTP断开连接成功";
} catch (IOException e) {
result ="FTP断弄出错:"+e.getMessage();
}
return result;
};
}
自定义触发事件理解
刚才开始接触JeanBean开发时,自定义触发器(WHEN-CUSTOM-ITEM-EVENT)一直不好解理。通开发实践得出结论:任何属性赋值或获得属性值都可以自定义触发事件,其中代码如下:
/**OPENFILE属性赋值时触发自定义事件
* this.getHandler 获得事件管理句柄给OPENFILE属性
* OPENFILE 是声明给属性值OPENFILE赋值时触发事件
*/
CustomEvent ce = new CustomEvent(this.getHandler(), OPENFILE);
this.getHandler().setProperty(ERRORMESSAGE,result);//设置错误信息属性值
this.dispatchCustomEvent(ce); //派发事件
Form核心包代码
1.文件操作程序单元包:OPERATORFILE_PKG
PACKAGE OPERATORFILE_PKG IS
/*
设置上传或读取文件总数量和当前文件索引号的目的:用于客制化触发事件时显示进度条
*/
fileTotal Number := 0; --上传文件总数量
fileIndex Number := 0; --当前文件索引号:选择多个文件中的第几个文件
javaBean Varchar2(200); --JavaBean项目名格式:BLOCK_NAME.ITEM_NAME
operatorLog Varchar2(200); --文件操作日志记录的项目名,其格式:BLOCK_NAME.ITEM_NAME
ftpUploadPath Varchar2(360); --上传至FTP服务器文件夹路径
localPath Varchar2(360) := ''; --FTP下载至本地文件的路径
IsOverWrite Varchar2(1) := 'N'; --是否允许覆盖:Y表示允许覆盖,N表示不允许覆盖
IsExistsFile Varchar2(1) := 'N'; --文件是否存在:Y表存在,N表示不存在
OrganizationId Number; --织组标识
UserId Number; --用户标识
FileCategoryId Number; --文件类别
--设置自定义JavaBean属性值
procedure setCustProperty(P_PROPERTY_ID Varchar2, P_VALUE Varchar2);
/*上传文件至FTP服务器
P_FTPHOST FTP服务器地址或IP
P_PORT FTP服务端口
P_USERNAME FTP服务登陆的用户
P_PASSWORD FTP用户的密码
P_FTPPATH FTP服务器上传的目录
P_ORG_ID 库存组织标识
P_USER_ID Oracle EBS操作用户标识
P_FILE_CATEGORY_ID 文件类别,
P_OVERWRITE 是否覆盖*/
procedure UploadFile(P_FTPHOST Varchar2,
P_PORT Number,
P_USERNAME Varchar2,
P_PASSWORD Varchar2,
P_FTPPATH Varchar2,
P_ORG_ID Number,
P_USER_ID Number,
P_FILE_CATEGORY_ID Number,
P_OVERWRITE Varchar2);
/*读取本地(共享盘)文件信息如文件名,文件路径
P_ORG_ID 库存组织标识
P_USER_ID Oracle EBS操作用户标识
P_FILE_CATEGORY_ID 文件类别,
P_OVERWRITE 是否覆盖*/
procedure ReadFile(P_ORG_ID Number,
P_USER_ID Number,
P_FILE_CATEGORY_ID Number,
P_OVERWRITE Varchar2);
--获得参数列表清单
Function getParameterList Return ParamList;
/*获得客制化触发事件属性值
P_PARAMETERLIST 参数列表清单
P_PROPERTY_ID 自定义属性值
返回 参数值*/
function getParameterValue(P_PARAMETERLIST ParamList,
P_PROPERTY_ID Varchar2) Return Varchar2;
--上传或读邓下一个文件
procedure operatorNextFile(P_FILE_PROPERTY Varchar2);
--显示上传或读取文件的进度条
procedure showProcessBar(P_TEXT Varchar2);
--上传文件或读取文件时,选择文件触发事件
procedure ftpUpload_Event(X_ERROR_MSG In Out Varchar2);
--上传文件或读取文件时,获得文件信息触发事件
procedure fileIndex_Event(X_ERROR_MSG In Out Varchar2);
--上传文件以后触发事件
procedure fileId_Event(X_ERROR_MSG In Out Varchar2);
/*创建FTP下载连接和获得本地文件夹路径
P_FTPHOST FTP服务器地址或IP
P_PORT FTP服务端口
P_USERNAME FTP服务登陆的用户
P_PASSWORD FTP用户的密码*/
procedure ftpDownload(P_FTPHOST Varchar2,
P_PORT Number,
P_USERNAME Varchar2,
P_PASSWORD Varchar2);
/*下载FTP服务器文件
P_FTPDOWNLOADPATH FTP下载文件夹
P_LOCALFILENAME 本地文件名称
P_SERVERFILENAME FTP服务器文件名称*/
procedure downloadFile(P_FTPDOWNLOADPATH Varchar2,
P_LOCALFILENAME Varchar2,
P_SERVERFILENAME Varchar2);
--FTP下载文件触发事件
procedure downloadFile_Event(X_ERROR_MSG In Out Varchar2);
/*文件基本操作触发事件包括如下
下载FTP文文件
打开本地文件
打印本地文件*/
procedure baseOperatorFile_Event(X_ERROR_MSG In Out Varchar2);
--打开本地文件
procedure openFile(P_LOCALPATH Varchar2);
--打印本地文件
procedure printFile(P_LOCALPATH Varchar2);
--新增或更新技术图纸记录
procedure AddUpdateRecord(P_FILE_NAME Varchar2,
P_FILESUFFIX Varchar2,
P_LOCALFILE Varchar2,
X_FILE_ID In Out Number);
--
Function FtpClose Return Varchar2;
END;
2.文件操作包体:OPERATORFILE_PKG
PACKAGE BODY OPERATORFILE_PKG IS
--设置自定义JavaBean属性值
procedure setCustProperty(P_PROPERTY_ID Varchar2, P_VALUE Varchar2) Is
Begin
set_custom_property(OPERATORFILE_PKG.javaBean,
1,
P_PROPERTY_ID,
P_VALUE);
End;
/*上传文件至FTP服务器
P_FTPHOST FTP服务器地址或IP
P_PORT FTP服务端口
P_USERNAME FTP服务登陆的用户
P_PASSWORD FTP用户的密码
P_FTPPATH FTP服务器上传的目录
P_ORG_ID 库存组织标识
P_USER_ID Oracle EBS操作用户标识
P_FILE_CATEGORY_ID 文件类别,
P_OVERWRITE 是否覆盖*/
procedure UploadFile(P_FTPHOST Varchar2,
P_PORT Number,
P_USERNAME Varchar2,
P_PASSWORD Varchar2,
P_FTPPATH Varchar2,
P_ORG_ID Number,
P_USER_ID Number,
P_FILE_CATEGORY_ID Number,
P_OVERWRITE Varchar2) Is
Begin
OPERATORFILE_PKG.fileTotal := 0;
OPERATORFILE_PKG.fileIndex := 0;
OPERATORFILE_PKG.ftpUploadPath := P_FTPPATH;
OPERATORFILE_PKG.OrganizationId := P_ORG_ID;
OPERATORFILE_PKG.UserId := P_USER_ID;
OPERATORFILE_PKG.FileCategoryId := P_FILE_CATEGORY_ID;
OPERATORFILE_PKG.IsOverWrite := P_OVERWRITE;
setCustProperty('FTPHOST', P_FTPHOST);
setCustProperty('PORT', P_PORT);
setCustProperty('USERNAME', P_USERNAME);
setCustProperty('PASSWORD', P_PASSWORD);
--Fnd_Message.Debug('P_FTPPATH:'||P_FTPPATH);
setCustProperty('FTPUPLOAD', P_FTPPATH);
End;
/*读取本地(共享盘)文件信息如文件名,文件路径
P_ORG_ID 库存组织标识
P_USER_ID Oracle EBS操作用户标识
P_FILE_CATEGORY_ID 文件类别,
P_OVERWRITE 是否覆盖*/
procedure ReadFile(P_ORG_ID Number,
P_USER_ID Number,
P_FILE_CATEGORY_ID Number,
P_OVERWRITE Varchar2) Is
Begin
OPERATORFILE_PKG.fileTotal := 0;
OPERATORFILE_PKG.fileIndex := 0;
OPERATORFILE_PKG.ftpUploadPath := '';
OPERATORFILE_PKG.OrganizationId := P_ORG_ID;
OPERATORFILE_PKG.UserId := P_USER_ID;
OPERATORFILE_PKG.FileCategoryId := P_FILE_CATEGORY_ID;
OPERATORFILE_PKG.IsOverWrite := P_OVERWRITE;
setCustProperty('FTPUPLOAD', '');
End;
--获得参数列表清单
Function getParameterList Return ParamList Is
Begin
Return Get_Parameter_List(:SYSTEM.CUSTOM_ITEM_EVENT_PARAMETERS);
End;
/*获得客制化触发事件属性值
P_PARAMETERLIST 参数列表清单
P_PROPERTY_ID 自定义属性值
返回 参数值*/
function getParameterValue(P_PARAMETERLIST ParamList,
P_PROPERTY_ID Varchar2) Return Varchar2 Is
l_ParameterType Number;
l_ParameterValue Varchar2(2000);
Begin
Get_Parameter_Attr(P_PARAMETERLIST,
P_PROPERTY_ID,
l_ParameterType,
l_ParameterValue);
Return l_ParameterValue;
End;
--上传或读邓下一个文件
procedure operatorNextFile(P_FILE_PROPERTY Varchar2) Is
Begin
OPERATORFILE_PKG.fileIndex := OPERATORFILE_PKG.fileIndex + 1;
If (OPERATORFILE_PKG.fileTotal > 0 And
OPERATORFILE_PKG.fileIndex < OPERATORFILE_PKG.fileTotal) Then
setCustProperty(P_FILE_PROPERTY, OPERATORFILE_PKG.fileIndex);
End If;
End;
--显示上传或读取文件的进度条
procedure showProcessBar(P_TEXT Varchar2) Is
Begin
If (OPERATORFILE_PKG.fileTotal > 0) Then
APP_WINDOW.PROGRESS((OPERATORFILE_PKG.fileIndex + 1) /
OPERATORFILE_PKG.fileTotal,
P_TEXT);
End If;
End;
--上传文件或读取文件时,选择文件以后触发事件 返回错误信息
procedure ftpUpload_Event(X_ERROR_MSG In Out Varchar2) Is
l_ParamList ParamList;
l_Success Varchar2(20); --创建FTPClient对象是否成功!
l_Result Varchar2(3000); --操作结果
Begin
l_ParamList := OPERATORFILE_PKG.getParameterList;
If (Id_Null(l_ParamList)) Then
X_ERROR_MSG := '读取文件操作出错!';
Return;
End If;
--创建FTPClient对象是否成功
l_Success := getParameterValue(l_ParamList, 'SUCCESS');
--
l_Result := getParameterValue(l_ParamList, 'ERRORMESSAGE');
--获得选择的文件数量
Begin
OPERATORFILE_PKG.fileTotal := To_Number(getParameterValue(l_ParamList,
'FILETOTAL'));
Exception
When Others Then
OPERATORFILE_PKG.fileTotal := 0;
End;
If (l_Success = 'false') Then
X_ERROR_MSG := l_Result;
Else
If (l_Result = '' Or l_Result Is Null) Then
X_ERROR_MSG := '总共选择了' || OPERATORFILE_PKG.fileTotal || '文件';
Else
X_ERROR_MSG := l_Result || Chr(13) || Chr(10) || '总共选择了' ||
OPERATORFILE_PKG.fileTotal || '文件';
End If;
operatorNextFile('FILEINDEX');
End If;
End;
--上传文件或读取文件时,获得文件信息触发事件
procedure fileIndex_Event(X_ERROR_MSG In Out Varchar2) Is
l_ParamList ParamList;
l_FileName Varchar2(360); --文件名称
l_fileSuffix Varchar2(60); --文件后缀名称 如:.doc,.xlsx
l_localFile Varchar2(360); --文件绝对路径(包括文件名)
l_FileId Number; --文件标识,来源数据库
Begin
l_ParamList := OPERATORFILE_PKG.getParameterList;
If (Id_Null(l_ParamList)) Then
X_ERROR_MSG := '读取文件操作出错!';
Return;
End If;
--获得错误信息
X_ERROR_MSG := getParameterValue(l_ParamList, 'ERRORMESSAGE');
--要上传或读取文件被删除时,产生错误,则上传或读取下一个文件
If (X_ERROR_MSG Is Not Null) Then
operatorNextFile('FILEINDEX');
Return;
End If;
--文件名称
l_FileName := getParameterValue(l_ParamList, 'FILENAME');
--文件后缀名称 如:.doc,.xlsx
l_fileSuffix := getParameterValue(l_ParamList, 'FILESUFFIX');
--文件绝对路径(包括文件名)
l_localFile := getParameterValue(l_ParamList, 'LOCALFILE');
--****Start 操作数据记录上传或读取文件信息-----
OPERATORFILE_PKG.AddUpdateRecord(P_FILE_NAME => l_FileName,
P_FILESUFFIX => l_fileSuffix,
P_LOCALFILE => l_localFile,
X_FILE_ID => l_FileId);
--****End 操作数据记录上传或读取文件信息-----
/*Fnd_Message.Debug('ftpUploadPath:'||OPERATORFILE_PKG.ftpUploadPath
|| ',IsOverWrite:' || OPERATORFILE_PKG.IsOverWrite
|| ',IsExistsFile:' || OPERATORFILE_PKG.IsExistsFile
|| ',l_FileId:' || l_FileId);*/
If (OPERATORFILE_PKG.ftpUploadPath Is Not Null) Then
--不允许覆盖并且文件已经存在,则上传或读取下一个文件
If (OPERATORFILE_PKG.IsOverWrite = 'N' And
OPERATORFILE_PKG.IsExistsFile = 'Y') Then
showProcessBar(l_localFile || ',信息读取成功!');
operatorNextFile('FILEINDEX');
Else
--Fnd_Message.Debug('l_FileId:' || l_FileId);
setCustProperty('FILEID', l_FileId);
End If;
Else
showProcessBar(l_localFile || ',信息读取成功!');
operatorNextFile('FILEINDEX');
End If;
End;
--上传文件以后触发事件
procedure fileId_Event(X_ERROR_MSG In Out Varchar2) Is
l_ParamList ParamList;
l_localFile Varchar2(360); --文件绝对路径(包括文件名)
l_Success Varchar2(20); --FTP下载文件是否成功!
l_Result Varchar2(3000); --操作结果
Begin
l_ParamList := OPERATORFILE_PKG.getParameterList;
If (Id_Null(l_ParamList)) Then
X_ERROR_MSG := '上传文件操作出错!';
Return;
End If;
l_Success := getParameterValue(l_ParamList, 'SUCCESS');
--文件绝对路径(包括文件名)
l_localFile := getParameterValue(l_ParamList, 'LOCALFILE');
--文件上传操作结果
l_Result := getParameterValue(l_ParamList, 'ERRORMESSAGE');
If (l_Success = 'true') Then
showProcessBar(l_localFile || ',上传或读取成功!');
Else
X_ERROR_MSG := l_localFile || ',上传或读取失败!' || l_Result;
showProcessBar(X_ERROR_MSG);
End If;
operatorNextFile('FILEINDEX');
--FTP注销登陆和断开连接
/*If(OPERATORFILE_PKG.ftpUploadPath Is Not Null
And (OPERATORFILE_PKG.fileTotal-OPERATORFILE_PKG.fileIndex)=1)Then
X_ERROR_MSG := OPERATORFILE_PKG.FtpClose;
End If;*/
End;
/*创建FTP下载连接和获得本地文件夹路径
P_FTPHOST FTP服务器地址或IP
P_PORT FTP服务端口
P_USERNAME FTP服务登陆的用户
P_PASSWORD FTP用户的密码*/
procedure ftpDownload(P_FTPHOST Varchar2,
P_PORT Number,
P_USERNAME Varchar2,
P_PASSWORD Varchar2) Is
Begin
OPERATORFILE_PKG.fileTotal := 0;
OPERATORFILE_PKG.fileIndex := 0;
setCustProperty('FTPHOST', P_FTPHOST);
setCustProperty('PORT', P_PORT);
setCustProperty('USERNAME', P_USERNAME);
setCustProperty('PASSWORD', P_PASSWORD);
localPath := Get_Custom_Property(OPERATORFILE_PKG.javaBean,
1,
'FTPDOWNLOAD');
End;
/*下载FTP服务器文件
P_FTPDOWNLOADPATH FTP下载文件夹
P_LOCALFILENAME 本地文件名称
P_SERVERFILENAME FTP服务器文件名称*/
procedure downloadFile(P_FTPDOWNLOADPATH Varchar2,
P_LOCALFILENAME Varchar2,
P_SERVERFILENAME Varchar2) Is
Begin
setCustProperty('FTPDOWNLOADPATH', P_FTPDOWNLOADPATH);
setCustProperty('LOCALFILENAME', P_LOCALFILENAME);
setCustProperty('DOWNLOADFILE', P_SERVERFILENAME);
End;
--FTP下载文件触发事件
procedure downloadFile_Event(X_ERROR_MSG In Out Varchar2) Is
l_ParamList ParamList;
l_Success Varchar2(20); --FTP下载文件是否成功!
l_Result Varchar2(4000);
Begin
l_ParamList := OPERATORFILE_PKG.getParameterList;
If (Id_Null(l_ParamList)) Then
X_ERROR_MSG := '下载文件操作出错!';
Return;
End If;
--FTP下载文件是否成功!
l_Success := getParameterValue(l_ParamList, 'SUCCESS');
--文件下载操作结果
l_Result := getParameterValue(l_ParamList, 'ERRORMESSAGE');
X_ERROR_MSG := l_Result;
End;
/*文件基本操作触发事件包括如下
下载FTP文文件
打开本地文件
打印本地文件*/
procedure baseOperatorFile_Event(X_ERROR_MSG In Out Varchar2) Is
l_ParamList ParamList;
Begin
l_ParamList := OPERATORFILE_PKG.getParameterList;
If (Id_Null(l_ParamList)) Then
X_ERROR_MSG := '下载文件操作出错!';
Return;
End If;
--获得错误信息
X_ERROR_MSG := getParameterValue(l_ParamList, 'ERRORMESSAGE');
End;
--打开本地文件
procedure openFile(P_LOCALPATH Varchar2) Is
Begin
setCustProperty('OPENFILE', P_LOCALPATH);
End;
--打印本地文件
procedure printFile(P_LOCALPATH Varchar2) Is
Begin
setCustProperty('PRINTFILE', P_LOCALPATH);
End;
--新增或更新技术图纸记录
procedure AddUpdateRecord(P_FILE_NAME Varchar2,
P_FILESUFFIX Varchar2,
P_LOCALFILE Varchar2,
X_FILE_ID In Out Number) Is
l_FileId Number;
l_FtpUploadFile Varchar2(360);
l_ItemId Number := Null;
Begin
--找查文件名是否存在
Begin
Select FILE_ID
Into l_FileId
From CUX.CUX_WIP_MFGDRAW
Where FILE_NAME = P_FILE_NAME;
OPERATORFILE_PKG.IsExistsFile := 'Y';
Exception
When No_Data_Found Then
l_FileId := 0;
OPERATORFILE_PKG.IsExistsFile := 'N';
End;
If (Nvl(l_FileId, 0) = 0) Then
Begin
Select MSI.INVENTORY_ITEM_ID
Into l_ItemId
From MTL_SYSTEM_ITEMS_B MSI
Where MSI.SEGMENT1 = SubStr(P_FILE_NAME, 1, 12)
And MSI.ORGANIZATION_ID = :parameter.ORGANIZATION_ID;
Exception
When No_Data_Found Then
Null;
End;
Select CUX.CUX_WIP_MFGDRAW_S.NEXTVAL Into l_FileId From Dual;
If (OPERATORFILE_PKG.ftpUploadPath Is Not Null) Then
l_FtpUploadFile := l_FileId || P_FILESUFFIX;
Else
l_FtpUploadFile := '';
End If;
Begin
Insert Into CUX.CUX_WIP_MFGDRAW
(FILE_ID,
ORGANIZATION_ID,
INVENTORY_ITEM_ID,
FILE_NAME,
CLIENT_FILE_PATH,
SERVER_FILE_PATH,
FILE_CATEGORY_ID,
CREATION_DATE,
CREATED_BY,
LAST_UPDATE_DATE,
LAST_UPDATED_BY,
LAST_UPDATE_LOGIN)
Values
(l_FileId,
OPERATORFILE_PKG.OrganizationId,
l_ItemId,
P_FILE_NAME,
P_LOCALFILE,
l_FtpUploadFile,
OPERATORFILE_PKG.FileCategoryId,
Sysdate,
OPERATORFILE_PKG.UserId,
Sysdate,
OPERATORFILE_PKG.UserId,
0);
forms_ddl('commit');
Exception
When Others Then
Null;
End;
Else
If (OPERATORFILE_PKG.IsOverWrite = 'Y') Then
Update CUX.CUX_WIP_MFGDRAW
Set CLIENT_FILE_PATH = P_LOCALFILE,
FILE_CATEGORY_ID = OPERATORFILE_PKG.FileCategoryId,
LAST_UPDATE_DATE = Sysdate,
LAST_UPDATED_BY = OPERATORFILE_PKG.UserId
Where FILE_ID = l_FileId;
forms_ddl('commit');
End If;
End If;
X_FILE_ID := l_FileId;
End;
--FTP注销登陆和断开连接
Function FtpClose Return Varchar2 Is
l_ErrorMsg Varchar2(2000);
Begin
l_ErrorMsg := Get_Custom_Property(OPERATORFILE_PKG.javaBean,
1,
'FTPCLOSE');
Return l_ErrorMsg;
End;
END;
调用JavaBean实例代码
1.Bean Area对象
1.属性设置
属性 |
值 |
Name |
OPERATORFILE |
Item Type |
Bean Area |
Implementation Class |
oracle.forms.fd.OperatorFile |
Canves |
指定画布 |
2.自定义触发事件: WHEN-CUSTOM-ITEM-EVENT
DECLARE
l_EventName Varchar2(30) := :system.custom_item_event;
l_ErrorMsg Varchar2(4000);
BEGIN
set_application_property(cursor_style, 'BUSY');
SYNCHRONIZE;
If(l_EventName='FTPUPLOAD')Then --SERVERDIRECTORY 获得上传或读取选择文件总个数
OPERATORFILE_PKG.ftpUpload_Event(l_ErrorMsg);
ElsIf(l_EventName='FILEINDEX')Then --获得文件名和本地文件路径
OPERATORFILE_PKG.fileIndex_Event(l_ErrorMsg);
ElsIf(l_EventName='FILEID')Then --获得文件是否上传成功
OPERATORFILE_PKG.fileId_Event(l_ErrorMsg);
ElsIf(l_EventName='DOWNLOADFILE')Then --下载文件
OPERATORFILE_PKG.downloadFile_Event(l_ErrorMsg);
ElsIf(l_EventName In ('FTPDOWNLOAD','PRINTFILE','OPENFILE') )Then
OPERATORFILE_PKG.baseOperatorFile_Event(l_ErrorMsg);
Else
Null;
End If;
If(l_ErrorMsg Is Null Or l_ErrorMsg ='')Then
Return;
End If;
If(:CONTROL.OPERATORLOG Is Not Null)Then
:CONTROL.OPERATORLOG := :CONTROL.OPERATORLOG || Chr(13)||Chr(10) || l_ErrorMsg;
Else
:CONTROL.OPERATORLOG := l_ErrorMsg;
End If;
END;
2.FTP上传和读取文件
1.FTP上传文件
Declare
l_FtpUploadPath Varchar2(360);
Begin
If (:CONTROL.FILE_CATEGORY_NAME Is Null Or
:CONTROL.FILE_CATEGORY_ID Is Null) Then
Fnd_Message.Debug('上传或读取文件之前,必须要选择文件类别!');
Go_Item('CONTROL.FILE_CATEGORY_NAME');
Raise Form_Trigger_Failure;
End If;
:CONTROL.OPERATORLOG := Null;
OPERATORFILE_PKG.javaBean := 'CONTROL.OPERATORFILE';
l_FtpUploadPath := '/app/gbdevcomn/html/gobao/' || :CONTROL.FILE_DIR || '/';
--Fnd_Message.Debug(l_FtpUploadPath);
OPERATORFILE_PKG.UploadFile(P_FTPHOST => '202.168.235.132',
P_PORT => 21,
P_USERNAME => 'appldev',
P_PASSWORD => 'appldev',
P_FTPPATH => l_FtpUploadPath,
P_ORG_ID => :parameter.ORGANIZATION_ID,
P_USER_ID => :parameter.USER_ID,
P_FILE_CATEGORY_ID => :CONTROL.FILE_CATEGORY_ID,
P_OVERWRITE => :CONTROL.OVERWRITE);
End;
2.读取文件信息:文件名和文件路径
Declare
l_FtpUploadPath Varchar2(360);
Begin
If (:CONTROL.FILE_CATEGORY_NAME Is Null Or
:CONTROL.FILE_CATEGORY_ID Is Null) Then
Fnd_Message.Debug('上传或读取文件之前,必须要选择文件类别!');
Go_Item('CONTROL.FILE_CATEGORY_NAME');
Raise Form_Trigger_Failure;
End If;
:CONTROL.OPERATORLOG := Null;
OPERATORFILE_PKG.javaBean := 'CONTROL.OPERATORFILE';
--Fnd_Message.Debug(l_FtpUploadPath);
OPERATORFILE_PKG.ReadFile(P_ORG_ID => :parameter.ORGANIZATION_ID,
P_USER_ID => :parameter.USER_ID,
P_FILE_CATEGORY_ID => :CONTROL.FILE_CATEGORY_ID,
P_OVERWRITE => :CONTROL.OVERWRITE);
End;
3.FTP下载文件
Declare
l_FtpUploadPath Varchar2(360);
l_ErrorMsg Varchar2(2000);
Begin
set_application_property(cursor_style, 'BUSY');
SYNCHRONIZE;
If (:CONTROL.FILE_DIR Is Null) Then
Fnd_Message.Debug('下载文件之前,必须要选择文件类别!');
Go_Item('CONTROL.FILE_CATEGORY_NAME');
Raise Form_Trigger_Failure;
End If;
:CONTROL.OPERATORLOG := Null;
l_FtpUploadPath := '/app/gbdevcomn/html/gobao/' ||
:CONTROL.FILE_DIR;
OPERATORFILE_PKG.javaBean := 'CONTROL.OPERATORFILE';
OPERATORFILE_PKG.ftpDownload(P_FTPHOST => '202.168.235.132',
P_PORT => 21,
P_USERNAME => 'appldev',
P_PASSWORD => 'appldev');
Go_Block('MFGDWG');
First_Record;
Loop
OPERATORFILE_PKG.downloadFile(P_FTPDOWNLOADPATH => l_FtpUploadPath,
P_LOCALFILENAME => :MFGDWG.FILE_NAME,
P_SERVERFILENAME => :MFGDWG.SERVER_FILE_PATH);
If (:system.last_record <> 'TRUE') Then
next_record;
Else
exit;
End If;
End Loop;
End;
4.打开本地文件
If(:MFGDWG.CLIENT_FILE_PATH Is Not Null)Then
:CONTROL.OPERATORLOG := Null;
OPERATORFILE_PKG.javaBean :='CONTROL.OPERATORFILE';
OPERATORFILE_PKG.openFile(:MFGDWG.CLIENT_FILE_PATH);
End If;
5.打印本地文件
If(:MFGDWG.CLIENT_FILE_PATH Is Not Null)Then
:CONTROL.OPERATORLOG := Null;
OPERATORFILE_PKG.javaBean :='CONTROL.OPERATORFILE';
OPERATORFILE_PKG.printFile(:MFGDWG.CLIENT_FILE_PATH);
End If;
异常问题处理
1.Swing组件
开发的JavaBean类初始化时,无法引用于java.swing.*包中的组件布局在Form画布上。但是,网上介绍Oracle Forms 9.0.2以上的版本是可以在Form画布中布局。不知道是不是Oracle Forms 6i不支持问题?还是其它原因。
2.中文文件名乱码
通常用中文命名文件名称,上传到Oracle EBS应用层服器上指定目录文件名变成乱码,非常头疼的问题。目前,解决方法将文件名转换成数字或英文名称,下载时候再将其转换成当前上传的文件名。
3.Form与JavaBean之间传值
在Form中给JavaBean属性FTPUPLOAD(FTP上传到服务器指定目录)赋值空时表示读取文件信息,如下:
set_custom_property(OPERATORFILE_PKG.javaBean,1,'FTPUPLOAD','');
而在JavaBean对应变量获得的值为false,因此,针对空值时必须要条件判断如下
关于服务器上的第三方jar部署和java程序在Oracle EBS服务器上发布,下一篇blog给大家讲一进,先给像我比较急性子的人看一下FTP上传文件或读取文件的效果图吧
1.打开Form表单之前会弹出安全警告如下图,选择“总是授权”
2.选择要上传的文件,可以选择多个如下图,测试FTP上传文件