This is a quick article on generating a file with the Zoho Deluge function .toFile() and uploading it to a file upload field within Zoho Creator.
Why?
The use-case here is that we want a file to be hosted within Zoho Creator for use by a JS widget that will download the CSV (in this case a Text *.txt) file for use by a dynamic auto-suggester dropdown; one of those fancy ones that includes photos and a bit of fuzzy logic.
I thought I could simply update the field with the new file but as I'm not downloading it, this is apparently not the process.
How?
As a high-level overview: we'll generate the CSV rows and then a file; then we'll use invokeURL to upload the file.
Generating the CSV
Here's the simplified code to generate the CSV - note that I am replacing commas with the HTML entity equivalent and enclosing the ID in double-quotes in case I open it in MS Excel or another system that likes rounding 64-bit signed integers (long numbers):
copyraw
// // Generate a CSV of a Report in ZohoCreator l_CsvLines = List(); l_ApplicableProducts = Products[Display_in_Widget=="Yes"] sort by Product_Name; for each c_Product in l_ApplicableProducts { l_CsvRow = List(); l_CsvRow.add(c_Product.Photo); l_CsvRow.add(c_Product.Product_Name.replaceAll(",", ",", true)); l_CsvRow.add(c_Product.Product_Desc.replaceAll(",", ",", true)); l_CsvRow.add("\"" + c_Product.ID + "\""); l_CsvLines.add(l_CsvRow.toString()); }
- //
- // Generate a CSV of a Report in ZohoCreator
- l_CsvLines = List();
- l_ApplicableProducts = Products[Display_in_Widget=="Yes"] sort by Product_Name;
- for each c_Product in l_ApplicableProducts
- {
- l_CsvRow = List();
- l_CsvRow.add(c_Product.Photo);
- l_CsvRow.add(c_Product.Product_Name.replaceAll(",", ",", true));
- l_CsvRow.add(c_Product.Product_Desc.replaceAll(",", ",", true));
- l_CsvRow.add("\"" + c_Product.ID + "\"");
- l_CsvLines.add(l_CsvRow.toString());
- }
Generate the file
You may note that this generates a text file rather than a CSV, this is because our JS widget won't pack a CSV but it will pack text files.
copyraw
// // generate a CSV or TXT v_CSVFilename = "applicable_products.txt"; f_CSVFile = l_CsvLines.toString(zoho.encryption.urlDecode("%0A")).toFile(v_CSVFilename); f_CSVFile.setParamName("file");
- //
- // generate a CSV or TXT
- v_CSVFilename = "applicable_products.txt";
- f_CSVFile = l_CsvLines.toString(zoho.encryption.urlDecode("%0A")).toFile(v_CSVFilename);
- f_CSVFile.setParamName("file");
Get current file name (optional)
To check on filename changes, I run this bit of code to get the internal and current file name:
copyraw
// // get original document file (optional) - you need your own record ID here v_ZC_DocumentRecordID = 1234567890123456789; c_ExistingDocument = Document[ID == v_ZC_DocumentRecordID]; info c_ExistingDocument.Document_File;
- //
- // get original document file (optional) - you need your own record ID here
- v_ZC_DocumentRecordID = 1234567890123456789;
- c_ExistingDocument = Document[ID == v_ZC_DocumentRecordID];
- info c_ExistingDocument.Document_File;
Upload the generated file to the record
Note that this is overwriting the existing record and associated file. We have no intention of creating a new record per file... Saying that, the file name will change every time it is updated as you will see. Also note, I have a form called "Document", a report called "All Documents", and the file upload field is called "Document File":
copyraw
// // now upload updated file v_Endpoint = "https://creator.zoho.com/api/v2.1"+zoho.appuri+"report/All_Documents/"+v_ZC_DocumentRecordID+"/Document_File/upload"; r_Upload = invokeurl [ url :v_Endpoint type :POST files: f_CSVFile connection:"zcreator" ]; info r_Upload;
- //
- // now upload updated file
- v_Endpoint = "https://creator.zoho.com/api/v2.1"+zoho.appuri+"report/All_Documents/"+v_ZC_DocumentRecordID+"/Document_File/upload";
- r_Upload = invokeUrl
- [
- url :v_Endpoint
- type :POST
- files: f_CSVFile
- connection:"zcreator"
- ];
- info r_Upload;
Display new file name (optional)
copyraw
// // get updated document file (optional: integrity check) c_ExistingDocument = Document[ID == v_ZC_DocumentRecordID]; info c_ExistingDocument.Document_File;
- //
- // get updated document file (optional: integrity check)
- c_ExistingDocument = Document[ID == v_ZC_DocumentRecordID];
- info c_ExistingDocument.Document_File;
I have all of the above in the same function. I've split it out to explain parts but otherwise it is intended to be all in the same function as there are references to some variables in earlier snippets of code on this page.
Error(s):
2945: UPLOAD_RULE_NOT_CONFIGURED
Was happening when I was trying to update the Zoho Creator record, specifically the file upload field, with the file object directly, eg. <collection>.<field>=<file_object>.2945: UPLOAD_RULE_NOT_CONFIGURED
Also got this error if I failed to add the setParamName such as:3700: Unable to upload a file. Please check and try again.
If I test my connection or even change how I upload the file, this error no longer appears. This error seems to be at the end of a function which has already done a lot of processing. Here's a quick test snippet of code:copyrawAdditional: I thought having a file and then using ZohoCreator .content would be a good way to store data exceeding 64Kb but instead I found using additional multi-line fields performance-wise was better:void fn_UploadTest() { // // selecting a record which has a file upload field that we want to upload to c_Check = My_Form[ID == 123456]; if(c_Check.count() > 0) { // // A quick CSV line f_TestFile = "Test 1,Test 2,Test 3".toFile("test.csv"); f_TestFile.setParamName("file"); // // found if you open the report properties and select rename from the vertical ellipsis icon in the top right v_ReportLinkName = "All_Weekly_Calendar_Caches"; v_FileUploadFieldName = "Cached_DataFile"; v_RecordID = c_Check.ID.toString(); // // using API upload file endpoint (either endpoints seem to be valid) //v_Endpoint = "https://creator.zoho.com/api/v2.1"+zoho.appuri+"report/"+v_ReportLinkName+"/"+v_RecordID+"/"+v_FileUploadFieldName+"/upload"; v_Endpoint = "https://www.zohoapis.com/creator/v2.1/data"+zoho.appuri+"report/"+v_ReportLinkName+"/"+v_RecordID+"/"+v_FileUploadFieldName+"/upload?skip_workflow=['all']"; info v_Endpoint; // // upload the file m_Params = Map(); m_Params.put("file", f_TestFile); // // this will work r_Upload = invokeurl [ url :v_Endpoint type :POST parameters: m_Params content-type: "multipart/form-data" connection:"zcreator" ]; // // this also works r_Upload = invokeurl [ url :v_Endpoint type :POST files: f_TestFile connection:"zcreator" ]; info r_Upload; } }
- void fn_UploadTest()
- {
- //
- // selecting a record which has a file upload field that we want to upload to
- c_Check = My_Form[ID == 123456];
- if(c_Check.count() > 0)
- {
- //
- // A quick CSV line
- f_TestFile = "Test 1,Test 2,Test 3".toFile("test.csv");
- f_TestFile.setParamName("file");
- //
- // found if you open the report properties and select rename from the vertical ellipsis icon in the top right
- v_ReportLinkName = "All_Weekly_Calendar_Caches";
- v_FileUploadFieldName = "Cached_DataFile";
- v_RecordID = c_Check.ID.toString();
- //
- // using API upload file endpoint (either endpoints seem to be valid)
- //v_Endpoint = "https://creator.zoho.com/api/v2.1"+zoho.appuri+"report/"+v_ReportLinkName+"/"+v_RecordID+"/"+v_FileUploadFieldName+"/upload";
- v_Endpoint = "https://www.zohoapis.com/creator/v2.1/data"+zoho.appuri+"report/"+v_ReportLinkName+"/"+v_RecordID+"/"+v_FileUploadFieldName+"/upload?skip_workflow=['all']";
- info v_Endpoint;
- //
- // upload the file
- m_Params = Map();
- m_Params.put("file", f_TestFile);
- //
- // this will work
- r_Upload = invokeUrl
- [
- url :v_Endpoint
- type :POST
- parameters: m_Params
- content-type: "multipart/form-data"
- connection:"zcreator"
- ];
- //
- // this also works
- r_Upload = invokeUrl
- [
- url :v_Endpoint
- type :POST
- files: f_TestFile
- connection:"zcreator"
- ];
- info r_Upload;
- }
- }
copyraw// // bigger than 64kb c_Check.Cached_HTML = v_HtmlToCache; if(v_HtmlToCache.len()>65000) { c_Check.Cached_HTML = v_HtmlToCache.subString(0,65000); c_Check.Cached_HTML_2 = v_HtmlToCache.subString(65000); } if(v_HtmlToCache.len()>129999) { c_Check.Cached_HTML_2 = v_HtmlToCache.subString(65000,130000); c_Check.Cached_HTML_3 = v_HtmlToCache.subString(130000); }
- //
- // bigger than 64kb
- c_Check.Cached_HTML = v_HtmlToCache;
- if(v_HtmlToCache.len()>65000)
- {
- c_Check.Cached_HTML = v_HtmlToCache.subString(0,65000);
- c_Check.Cached_HTML_2 = v_HtmlToCache.subString(65000);
- }
- if(v_HtmlToCache.len()>129999)
- {
- c_Check.Cached_HTML_2 = v_HtmlToCache.subString(65000,130000);
- c_Check.Cached_HTML_3 = v_HtmlToCache.subString(130000);
- }
Category: Zoho :: Article: 870
Add comment