שמירת קובץ CSV במחשב האישי / שרת
מאמר זה יסביר כיצד ניתן לשמור במחשב האישי / שרת קובץ CSV המועבר כ-Base64.
לצורך הדוגמה, נייצר API פשוט אשר יבצע שמירה למחשב האישי.
נניח כי שם השדה המתקבל ב-Request נקרא csvFile.
לכן, נייצר Property חדש ב-API אשר נקרא לו base64File.
Property זה מחלץ את ה-Base64 שמאוחסן כמחרוזת בתא '0' של ה-CSV שהתקבל ב-jSON. (של ה-Request)
<property expression="json-eval($.csvFile[0].base64)" name="base64File" scope="default" type="STRING"/>
בגלל שה-Base64 של CSV אינו נקי (לפני ה-Base64 קיים חלק של data:text/csv;base64,), נצטרך לייצר Script אשר יבצע את הפעולות הבאות –
- ברגע שיגיע לפסיק, יבצע פיצול של המידע וישמור רק את החלק של ה-Base64 הנקי (ללא data:text/csv;base64,).
- מפענח את המידע מ-Base64 לטקסט קריא (CSV).
- שומר את הנתונים המפוענחים במשתנה שנקרא לו decodedCsvContent.
- הנתונים ישמרו בפורמט של UTF-8.
<script language="js"><![CDATA[var base64Data = mc.getProperty('base64File').split(',');
if (base64Data.length > 1) {
var decodedContent = java.util.Base64.getDecoder().decode(base64Data[1]);
mc.setProperty('decodedCsvContent', new java.lang.String(decodedContent, "UTF-8"));
}]]></script>
כעת נייצר משתנה ב-file.properties (תחת תיקיית 'Conf') אשר יכיל את את הנתיב שבו שיישמר הקובץ CSV הסופי.
למשל, בסביבה הלוקאלית הקובץ יוגדר להישמר במחשב האישי, ואם הפרויקט יהיה בסביבה אחרת אז נוכל להגדיר את הניתוב לשרת הלינוקס / Windows בהתאם לצורך.
לצורך הדוגמה, שם המשתנה יקרא localPathForCSVFile.
ב-file.properties נגדיר אותו כך-
localPathForCSVFile=C:/WSO2/test/files/
ניתן כמובן להגדיר כל תיקייה אחרת לפי הצורך.
אם מעוניינים להגדיר תיקייה ב-Linux, הניתוב נדרש להיות בצורה הבאה –
localPathForCSVFile=/home/srvadmin/test/
גם במקרה הנוכחי, יש לתת את שם התיקייה הרצויה.
כעת נייצר Property אשר יקרא למשתנה זה –
<property expression="get-property('file','localPathForCSVFile')" name="localPathForCSVFile" scope="default" type="STRING"/>
כעת נייצר Property נוסף עבור שם קובץ קבוע.
בסיום נבצע חיבור (contac) בין שני ה-Properties האחרונים בכדי לייצר Property חדש שיכיל הניתוב המלא של הנתיב + שם הקובץ.
<property value="csv_file.csv" name="csvFileName" scope="default" type="STRING"/>
<property expression="concat(get-property('localPathForCSVFile'), get-property('csvFileName'))" name="pathWithFullFileName" scope="default" type="STRING"/>
כעת נצטרך לייצר local-entry שמכיל פרטים על החיבור לשמירת הקובץ.
נקרא לו לשם הדוגמה local_test.
בקובץ זה ניתן להגדיר את סוג החיבור (לוקאלי, SFTP, FTP וכו'), מיקום היעד, מנגנון נעילה (Locking).
במקרה שלנו, אנו נשתמש בסוג חיבור פשוט לוקאלי.
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="local_test" xmlns="http://ws.apache.org/ns/synapse">
<file.init>
<name>local_test</name>
<fileLockScheme>Local</fileLockScheme>
<connectionType>LOCAL</connectionType>
</file.init>
</localEntry>
לבסוף, נצטרך להשתמש ב-File connector ע"מ לשמור את הקובץ במחשב / בשרת.
לשם כך, נשתמש ב-file.write.
יש לוודא כי ה-connector מוגדר בפרויקט ואקטיבי ב-Enterprise Integrator Management Console.
<file.write configKey="local_test">
<filePath>{get-property('pathWithFullFileExtention')}</filePath>
<contentOrExpression>{$ctx:decodedCsvContent}</contentOrExpression>
<mimeType>text/csv</mimeType>
<compress>false</compress>
<writeMode>Overwrite</writeMode>
<enableStreaming>false</enableStreaming>
<appendNewLine>false</appendNewLine>
<enableLock>false</enableLock>
<includeResultTo>Message Body</includeResultTo>
<updateLastModified>true</updateLastModified>
</file.write>
להלן הסבר על ההגדרות הראשיות ב-file.write:
filePath – הנתיב אליו יישמר הקובץ נקבע לפי ה-Property שהגדרנו קודם כן 'pathWithFullFileExtention'.
contentOrExpression – התוכן שישמר בקובץ 'decodedCsvContent' (הנתונים המפוענחים מה-Base64).
mimeType – סוג הקובץ שישמר יהיה csv.
writeMode – מאפשר כל פעם לדרוס את הקובץ בקובץ אחר בעל אותו השם.
לסיום, נציג דוגמה מלאה ל-API:
<?xml version="1.0" encoding="UTF-8"?>
<api context="/test/testFile" name="testFile" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<property expression="json-eval($.csvFile[0].base64)" name="base64File" scope="default" type="STRING"/>
<script language="js"><![CDATA[var base64Data = mc.getProperty('base64File').split(',');
if (base64Data.length > 1) {
var decodedContent = java.util.Base64.getDecoder().decode(base64Data[1]);
mc.setProperty('decodedCsvContent', new java.lang.String(decodedContent, "UTF-8"));
}]]></script>
<property expression="get-property('file','localPathForCSVFile')" name="localPathForCSVFile" scope="default" type="STRING"/>
<property value="csv_file.csv" name="csvFileName" scope="default" type="STRING"/>
<property expression="concat(get-property('localPathForCSVFile'), get-property('csvFileName'))" name="pathWithFullFileName" scope="default" type="STRING"/>
<file.write configKey="local_test">
<filePath>{get-property('pathWithFullFileExtention')}</filePath>
<contentOrExpression>{$ctx:decodedCsvContent}</contentOrExpression>
<mimeType>text/csv</mimeType>
<compress>false</compress>
<writeMode>Overwrite</writeMode>
<enableStreaming>false</enableStreaming>
<appendNewLine>false</appendNewLine>
<enableLock>false</enableLock>
<includeResultTo>Message Body</includeResultTo>
<updateLastModified>true</updateLastModified>
</file.write>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>