Dropzone
The purpose of this page is to explain how to use the Dropzone plugin within your CoT Form JSON definition.
Dependencies:
As am I writing this document the dropzone features are in the following CoreJs branch:
https://github.com/CityofToronto/corejs/tree/feature/dropzone
This branch was updated by merging CoreJs 9.3.0 in to it but the changes have not been released to CoreJs master yet.
In your package.json import it using:
"core": "git+https://github.com/CityofToronto/corejs.git#feature/dropzone",
Also in "coreConfig" part of package.json remember to include "includeDropzone": true
Upload API Dependency:
Since you are using Dropzone you will need an API where you will be saving the files. In this example I am using the Upload API v2 on the Maserati Environment.
http://maserati.corp.toronto.ca:9097/c3api_upload/
I asked the C3 API team to create my application service id named "nuit_blanche" I can login using my City of Toronto username and password to configure this API.
In my case I have configured my upload API to save images to the database but as you can see in the screenshot you can configure it to be NAS, SCP, or your own database (Client DB). Please read the Upload v2 API documentation to look at all of your options.
With this configuration the images will be saved to the database (not DataAccess, the upload API has it's own DB). The upload and retrieve ACL is anonymous for this example but it can be changed. The file size is configured on that interface as well, you want to make sure it matches the limit you have set on your Dropzone element.
Use Case:
Let's say you are building a form and you need to provide the ability for your users to upload images. For accessibility purposes we also need to capture the image alt text.
For this use case we have customized dropzone a bit to work with CoT Model and CoT Form.
Before we start with the code I think it will be helpful to understand all data integrations that will take place.
A CoT Form has a Model object to which all of the UI fields and mapped to, what we want to do is upload an image and get a reference to it and store it in our model. Next time when the model loads we will use the image reference to get the image file and display it in your application.
Upload Case: When the user uploads a image using dropzone and submits the page, the application will first send a submit request to the backend upload API. The upload API will save the image successfully and return back a URL or a BIN ID. After that is done our model is updated and the BIN ID or URL will be saved in our model the user also entered alt text which will be saved in our model as well. Now finally our model object is submitted to our backend (DataAccess API v2) and it is save (this is our saved entity).
Retrieve Case: When the user is viewing the records in your entity set the DataAccess API will return the the JSON representation of our model (our saved entity). This model will have reference to the image either a BIN ID or a URL. Using that reference (URL, or BIN ID) we will make another request to get/display the image for example the src field of an img tag would be a URL built using the reference value.
Code Example:
https://github.com/CityofToronto/feis_nuit_blanche
In your CoT Form define your dropzone type field.
In this case the Gulp file has the following value for the UPLOAD_URL (https://github.com/CityofToronto/feis_nuit_blanche/blob/master/gulpfile.js)
UPLOAD_URL: 'https://maserati.corp.toronto.ca:49097/c3api_upload/upload/nuit_blanche/images',
If you see the swagger documentation for Upload API v2: POST /upload/{Service ID}/{File Reference}
I am making the request to the Service ID which is 'nuit_blanche' and in my case I have put the 'File Reference' to be 'images'. It doesn't have to be 'images' it can be anything. The file reference is a way of grouping uploaded files, you will see below that my uploaded file's name has the word "images" which is the File Reference.
{ fields: [ { id: 'projectImages', title: 'Project Images', bindTo: 'projectImages', type: 'dropzone', options: { url: '/*@echo UPLOAD_URL */', "fields": [ { name: 'projectImageCutline', title: 'Image Caption', type: 'text', required: true } ] } } ] }
The link of our CoT Form and CoT Model is the field named "projectImages". In the CoT Model section I have commented the section on projectImages to show what the model will look like for my application logic but other fields will be added there by Dropzone (you will see this below).
In the form definition of the dropzone under the "fields" section I have one field named "projectImageCutline" this will will contain my image alt text.
(CoT Model) ProjectModel: https://github.com/CityofToronto/feis_nuit_blanche/blob/master/src/scripts/models/ProjectModel.js
let Project = CotModel.extend({ /* Begin Backbone methods */ defaults: function () { //default field values for new instances return { // Project Details "projectTitle": "", // migrated projectTitle // Other fields ... "projectImages": null, // [{ // "projectImageCutline": "" // }], // migrate projectImage, projectImageCutline // Other fields ... "projectAdvisories": "", // migrate advisory
Next when the user clicks save you need to make sure that dropzone uploads the images first and after it is done you can save your model. In most CoT Forms this will work by default since by default dropzone is integrated with the CoT From success method. In my case I have a many forms with multiple dropzones so I am not using the CoT Form success method. When user clicks the save button on my backbone view the event is captured and I manually save each of the Dropzone fields before calling the method to save my model to the backend.
'click .save-btn' : function(e) { let that = this; $("[name='sponsorImage']").get(0).cotDropzone.finalize( function() { $("[name='projectImages']").get(0).cotDropzone.finalize( function() { $("[name='print_promotion_images']").get(0).cotDropzone.finalize( function() { that.saveProject(); } ) } ) } ) },
Here is what happens when I click save, for completeness I have included the request and response the key parts you need to focus on is #2 and #5 below.
1 ) Dropzone Request
curl 'https://maserati.corp.toronto.ca:49097/c3api_upload/upload/nuit_blanche/images' -H 'Origin: http://evil.com/' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryE1s60KuXYtLGfgcP' -H 'Accept: application/json' -H 'Cache-Control: no-cache' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' -H 'Referer: https://was-intra-sit.toronto.ca/webapps/nuitblanche_admin/' --data-binary $'------WebKitFormBoundaryE1s60KuXYtLGfgcP\r\nContent-Disposition: form-data; name="file"; filename="Screen Shot 2019-01-28 at 10.42.27 AM.png"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundaryE1s60KuXYtLGfgcP--\r\n' --compressed --insecure
2) Dropzone Response
{"BIN_ID":[{"bin_id":"Zi2DZlGoy1yOa5dJGIQJoA","file_name":"53a165ad-df93-4f60-a57a-e12dcfe5f0b4-2019_01_28-images-Screen Shot 2019-01-28 at 10.42.27 AM.png"}]}
3) Model Request
curl 'https://maserati.corp.toronto.ca:49093/c3api_data/v2/DataAccess.svc/nuitblanche/projects' -H 'Origin: http://evil.com/' -H 'Accept-Encoding: gzip, deflate, br' -H 'Accept-Language: en-US,en;q=0.9' -H 'Authorization: AuthSession 9a31c8a4-efd4-4f2b-b5a9-ead3b949b248' -H 'Content-Type: application/json' -H 'Accept: application/json;odata.metadata=none' -H 'Referer: https://was-intra-sit.toronto.ca/webapps/nuitblanche_admin/' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' -H 'Connection: keep-alive' --data-binary '{"pid__migrated":"","projectTitle":"My Simple Project","partnerProject":"","curatorTitle":"","curatorName":"","exhibition":"","project_displayNumber":"","indoors_outdoors":"","year_of_work":"","install_type":"","install_type_other":"","timed_scheduled_components":"","projectType":"","projectUrls":[{"url":"","description":""}],"projectImages":[{"name":"Screen Shot 2019-01-28 at 10.42.27 AM.png","size":355910,"status":"success","type":"image/png","bin_id":"Zi2DZlGoy1yOa5dJGIQJoA","thumbnailDataUri":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFYElEQVRoQ9Wa61IiVxDH+8wAXlFRjJafLR9oHzKpvE6+aG2MupJiFUSQq8IMk/o1NkEiCOOM0Xanhrmcvv67T58z625ubiLP86TZbEq9XpeTkxMJw1AGg4FeHx8fi+/78lnJ/frb79FjryO5XE4eHx9la2tLut2uDIdDWVtbk2/fvkk2m/2s+ov74/wu2s721Mt43s9kZDgMxwpvbubFOScSRcIpHA6FiEmk/8T3nIThUJzn1GjI93wRJ3rNWP54W8c6b3TPExkMAvE8X+Vxhj9MPc9JEIbinCfRs7xIkO/E9zyVpwSfv65vo4f7iirPy3qOIhW+VyxKNpORSrUqYRBodIIwUHgNUdp58st+Ue4bDRX81H/S8fl8XvZ2C1Kp3MkgGMhWPi+rq6tS/vlTlchls3JweCA/flyrcZlMRjX3nqG6W9hRFHQ6XUUGxqAPuuzvF+XmpqI6crhWuxshFOOnCQ/DeOTB12kYReKp616SMn++P+KjQRnT5PPpsfDkXRs/+ZxIwMl4ubOzswhme3t7sr6+/mmxPksxVyqVIixF+c+crDMNaLfbFuHEvd9oNOT6+lqr2/b2tvInF46OjhJzlut0OqkZQOKRXxCJT0ISbarYa/iO40FXLpejarUqKysrmtUILBaLWgV6vZ4KQxE8d3h4uJSMp6cnnSDhCf92u62/Dw4OdI5Jglyr1dIkNuK3Ka016LmacE/r/xJkETCvm5xEI5AmhGhFLi8vNZI7OzvamjBhFgoFjUyn05H9/X3Z3d1VSGEgMKMiLgox12w2U8uBIAjGsKHC9fv90USWy2lOGLS4NiI6k9dvBdyFYZiKAVQePIqilOjRbJs8aQ4kz3bE0WCRFn+VwUTGD0K3ubmZqKfAPhWOM1XMIEQ+QOQDkdnY2Fi6QJhTXK1WUwMMm8tWmlneBd8clGPtcn1fyAnkYAzwQnnkkR+LJu20PPeihiYYaxSH8LrVf+YCjLB5hXeIhkUkjvhxDhhe43pilvDpOcai/R9PvtLRLmKQY0k5yZQ8SIqoRPRDeB3vMzNrX5/N6gGUIIyMmweuXq+PqxDeR9B7yfCPYiQw17owCQJVFtyTE5PdL3LjRN8FQZB4GQX3eB+lLFHf65RZ493Dw8MLCFlIJ71hOJ720DyPxfFmHCPd1dVVRJgJJx0i/QmhBp+E3bZcCDlrXYMA93nnoxSdGQGSmHJGqFEYY1DSEo37NF7Aweq3dabL9CxxvLvImFRyYBHBSb3zohv9v+EQxyh3e3s7rkJA5DNvI75moBqgO2XOaRJ/OQMGg0Hi80AcKMQdk+quRFyllhnnKpWKQsiWcoskMmW2XC6/aAfocyi5HK+V23l8WSvTI9kGAr+Zi0wn25rhORC3tkM3B8gB6rn1Jm8ZQJtgkxueQmGEQfCwJaQ1iPP4ohBjOeDLfGQLH65RlLzEOWacOcnmItfr9aJlthRtrwgG713n4mlziC14zHCMMsfOg9TSOTBvV3kZ7Nq70/zselE5rnpXjUZ7/aMPFPQ7X4nc9z+/R8FgtODAAJZ3rVZL8YwXDJPADCzatX0EsTDbLhybuB85l7jT01P9wIEinFGgVqvpNUqxUqK355okY8VGHvDM1rYYZ3hm3/O9ubEMAlwa2+tvVbJlFHzr3aWT+C2GH/3cNRoNbSXAbVJ7QmkaQR6WSiXVFai6i4sLnYnBfhIL+jSVt+WuTZzahJ5dnGkEVldWpZAvSMZPZxM2LcPc+d/nUX/Ql1w2J/m1/JcyQD+an1+c6/+VsL16MAacktzgSsv73V5XXPW+qjkQDf/9MB3nc1JaSs7jGw5D+fplNM1vZB8RlX8A2cA2K7BgoqcAAAAASUVORK5CYII=","file_name":"53a165ad-df93-4f60-a57a-e12dcfe5f0b4-2019_01_28-images-Screen Shot 2019-01-28 at 10.42.27 AM.png","projectImageCutline":"My Image"}],"projectAdvisories":"","projectContentCategory":[],"content_category_other":"","admin_projectUrls":[{"url":"","description":""}],"project_spotlight":"","sponserImage":null,"extended_project":"","acknowledgements":[{"type":"","type_other":"","description":"","display_on":[]}],"projectArtists":[{"first_name":"","last_name":"","hometown_city":"","hometown_country":"","website_url":""}],"projectCollective":[{"collective_name":"","hometown_city":"","hometown_country":"","website_url":""}],"artist_summary":"","admin_comments_artist":"","locations":[{"location_name":"","street_number":"","street_name":"","unit_number":"","postal_code":"","intersection_street_1":"","intersection_street_2":"","location_details":"","accessibility":"","public_washrooms":"","food_snacks":"","alcohol_service":"","proj_lat":"","proj_lng":""}],"admin_comments_location":"","social_media_links":[{"type":"","link":""}],"provide_images":"","project_description":"","for_nuit_blanche":"","previously_mounted":"","audience_participation":"","publications":[],"publication_details_arts_and_culture":"","publication_details_popular_culture":"","publication_details_other":"","media_release":"","pdf_word_file_upload":"","private_promotion_details":"","admin_comments_social_media":"","contact_firstname":"","contact_lastname":"","contact_position":"","contact_unit_number":"","contact_street_number":"","contact_street_name":"","contact_city":"","contact_province":"","contact_postal_code":"","contact_primary_phone":"","contact_alternate_phone":"","contact_email":"","event_contact_firstname":"","event_contact_lastname":"","event_contact_position":"","event_contact_primary_phone":"","event_contact_alternate_phone":"","event_contact_email":"","admin_comments_contact":"","estimated_traffic":"","ship_to_buidling_venue_name":"","ship_to_unit_number":"","ship_to_street_number":"","ship_to_street_name":"","ship_to_city":"","days_of_week":"","receiving_hours":"","special_instructions":"","receiver_first_name":"","receive_last_name":"","receive_position_title":"","receiver_primary_phone":"","receiver_alternate_phone":"","receiver_email":"","ship_project_to_event_guide_add":"","admin_comments_shipping":"","projectDescription_website":"","projectDescription_mobile":"","projectBio":[],"admin_special_notes":"","promotion_links":[{"name":"","description":"","url":""}],"admin_comments_digital_promotion":"","event_guide":"","print_promotion_images":null,"admin_comments_print":"","admin_programming_assigned_to":"","admin_programming_status":"","admin_marketing_assigned_to":"","admin_marketing_status":"","admin_master_assigned_to":"","admin_master_status":"","admin_project_owner_username":"","active_archive_project":"","show_hide_project":"","numberOfTours":0}' --compressed --insecure
4) Model Response
{"@odata":null,"__CreatedOn":"2019-01-28T11:37:36.578-05:00","__ModifiedOn":"2019-01-28T11:37:36.578-05:00","__Owner":"pdave2","__Status":"","acknowledgements":[{"description":"","type":"","type_other":""}],"active_archive_project":"","admin_comments_artist":"","admin_comments_contact":"","admin_comments_digital_promotion":"","admin_comments_location":"","admin_comments_print":"","admin_comments_shipping":"","admin_comments_social_media":"","admin_marketing_assigned_to":"","admin_marketing_status":"","admin_master_assigned_to":"","admin_master_status":"","admin_programming_assigned_to":"","admin_programming_status":"","admin_projectUrls":[{"description":"","url":""}],"admin_project_owner_username":"","admin_special_notes":"","artist_summary":"","audience_participation":"","contact_alternate_phone":"","contact_city":"","contact_email":"","contact_firstname":"","contact_lastname":"","contact_position":"","contact_postal_code":"","contact_primary_phone":"","contact_province":"","contact_street_name":"","contact_street_number":"","contact_unit_number":"","content_category_other":"","curatorName":"","curatorTitle":"","days_of_week":"","estimated_traffic":"","event_contact_alternate_phone":"","event_contact_email":"","event_contact_firstname":"","event_contact_lastname":"","event_contact_position":"","event_contact_primary_phone":"","event_guide":"","exhibition":"","extended_project":"","for_nuit_blanche":"","id":"546f79b1-971b-4106-a0a0-23c62cb177ef","indoors_outdoors":"","install_type":"","install_type_other":"","locations":[{"accessibility":"","alcohol_service":"","food_snacks":"","intersection_street_1":"","intersection_street_2":"","location_details":"","location_name":"","postal_code":"","proj_lat":"","proj_lng":"","public_washrooms":"","street_name":"","street_number":"","unit_number":""}],"media_release":"","numberOfTours":0,"partnerProject":"","pdf_word_file_upload":"","pid__migrated":"","previously_mounted":"","private_promotion_details":"","projectAdvisories":"","projectArtists":[{"first_name":"","hometown_city":"","hometown_country":"","last_name":"","website_url":""}],"projectBio":null,"projectCollective":[{"collective_name":"","hometown_city":"","hometown_country":"","website_url":""}],"projectDescription_mobile":"","projectDescription_website":"","projectImages":[{"bin_id":"Zi2DZlGoy1yOa5dJGIQJoA","file_name":"53a165ad-df93-4f60-a57a-e12dcfe5f0b4-2019_01_28-images-Screen Shot 2019-01-28 at 10.42.27 AM.png","initial":null,"name":"Screen Shot 2019-01-28 at 10.42.27 AM.png","projectImageCutline":"My Image","size":355910,"status":"success","thumbnailDataUri":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFYElEQVRoQ9Wa61IiVxDH+8wAXlFRjJafLR9oHzKpvE6+aG2MupJiFUSQq8IMk/o1NkEiCOOM0Xanhrmcvv67T58z625ubiLP86TZbEq9XpeTkxMJw1AGg4FeHx8fi+/78lnJ/frb79FjryO5XE4eHx9la2tLut2uDIdDWVtbk2/fvkk2m/2s+ov74/wu2s721Mt43s9kZDgMxwpvbubFOScSRcIpHA6FiEmk/8T3nIThUJzn1GjI93wRJ3rNWP54W8c6b3TPExkMAvE8X+Vxhj9MPc9JEIbinCfRs7xIkO/E9zyVpwSfv65vo4f7iirPy3qOIhW+VyxKNpORSrUqYRBodIIwUHgNUdp58st+Ue4bDRX81H/S8fl8XvZ2C1Kp3MkgGMhWPi+rq6tS/vlTlchls3JweCA/flyrcZlMRjX3nqG6W9hRFHQ6XUUGxqAPuuzvF+XmpqI6crhWuxshFOOnCQ/DeOTB12kYReKp616SMn++P+KjQRnT5PPpsfDkXRs/+ZxIwMl4ubOzswhme3t7sr6+/mmxPksxVyqVIixF+c+crDMNaLfbFuHEvd9oNOT6+lqr2/b2tvInF46OjhJzlut0OqkZQOKRXxCJT0ISbarYa/iO40FXLpejarUqKysrmtUILBaLWgV6vZ4KQxE8d3h4uJSMp6cnnSDhCf92u62/Dw4OdI5Jglyr1dIkNuK3Ka016LmacE/r/xJkETCvm5xEI5AmhGhFLi8vNZI7OzvamjBhFgoFjUyn05H9/X3Z3d1VSGEgMKMiLgox12w2U8uBIAjGsKHC9fv90USWy2lOGLS4NiI6k9dvBdyFYZiKAVQePIqilOjRbJs8aQ4kz3bE0WCRFn+VwUTGD0K3ubmZqKfAPhWOM1XMIEQ+QOQDkdnY2Fi6QJhTXK1WUwMMm8tWmlneBd8clGPtcn1fyAnkYAzwQnnkkR+LJu20PPeihiYYaxSH8LrVf+YCjLB5hXeIhkUkjvhxDhhe43pilvDpOcai/R9PvtLRLmKQY0k5yZQ8SIqoRPRDeB3vMzNrX5/N6gGUIIyMmweuXq+PqxDeR9B7yfCPYiQw17owCQJVFtyTE5PdL3LjRN8FQZB4GQX3eB+lLFHf65RZ493Dw8MLCFlIJ71hOJ720DyPxfFmHCPd1dVVRJgJJx0i/QmhBp+E3bZcCDlrXYMA93nnoxSdGQGSmHJGqFEYY1DSEo37NF7Aweq3dabL9CxxvLvImFRyYBHBSb3zohv9v+EQxyh3e3s7rkJA5DNvI75moBqgO2XOaRJ/OQMGg0Hi80AcKMQdk+quRFyllhnnKpWKQsiWcoskMmW2XC6/aAfocyi5HK+V23l8WSvTI9kGAr+Zi0wn25rhORC3tkM3B8gB6rn1Jm8ZQJtgkxueQmGEQfCwJaQ1iPP4ohBjOeDLfGQLH65RlLzEOWacOcnmItfr9aJlthRtrwgG713n4mlziC14zHCMMsfOg9TSOTBvV3kZ7Nq70/zselE5rnpXjUZ7/aMPFPQ7X4nc9z+/R8FgtODAAJZ3rVZL8YwXDJPADCzatX0EsTDbLhybuB85l7jT01P9wIEinFGgVqvpNUqxUqK355okY8VGHvDM1rYYZ3hm3/O9ubEMAlwa2+tvVbJlFHzr3aWT+C2GH/3cNRoNbSXAbVJ7QmkaQR6WSiXVFai6i4sLnYnBfhIL+jSVt+WuTZzahJ5dnGkEVldWpZAvSMZPZxM2LcPc+d/nUX/Ql1w2J/m1/JcyQD+an1+c6/+VsL16MAacktzgSsv73V5XXPW+qjkQDf/9MB3nc1JaSs7jGw5D+fplNM1vZB8RlX8A2cA2K7BgoqcAAAAASUVORK5CYII=","type":"image/png"}],"projectTitle":"My Simple Project","projectType":"","projectUrls":[{"description":"","url":""}],"project_description":"","project_displayNumber":"","project_spotlight":"","promotion_links":[{"description":"","name":"","url":""}],"provide_images":"","publication_details_arts_and_culture":"","publication_details_other":"","publication_details_popular_culture":"","receive_last_name":"","receive_position_title":"","receiver_alternate_phone":"","receiver_email":"","receiver_first_name":"","receiver_primary_phone":"","receiving_hours":"","ship_project_to_event_guide_add":"","ship_to_buidling_venue_name":"","ship_to_city":"","ship_to_street_name":"","ship_to_street_number":"","ship_to_unit_number":"","show_hide_project":"","social_media_links":[{"link":"","type":""}],"special_instructions":"","timed_scheduled_components":"","year_of_work":""}
5) For what we want to do notice inside the Model Response there is the projectImages section which has the value of the uploaded image. Most of these fields were added by Dropzone.
"projectImages":[{"name":"Screen Shot 2019-01-28 at 10.42.27 AM.png","size":355910,"status":"success","type":"image/png","bin_id":"Zi2DZlGoy1yOa5dJGIQJoA","thumbnailDataUri":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFYElEQVRoQ9Wa61IiVxDH+8wAXlFRjJafLR9oHzKpvE6+aG2MupJiFUSQq8IMk/o1NkEiCOOM0Xanhrmcvv67T58z625ubiLP86TZbEq9XpeTkxMJw1AGg4FeHx8fi+/78lnJ/frb79FjryO5XE4eHx9la2tLut2uDIdDWVtbk2/fvkk2m/2s+ov74/wu2s721Mt43s9kZDgMxwpvbubFOScSRcIpHA6FiEmk/8T3nIThUJzn1GjI93wRJ3rNWP54W8c6b3TPExkMAvE8X+Vxhj9MPc9JEIbinCfRs7xIkO/E9zyVpwSfv65vo4f7iirPy3qOIhW+VyxKNpORSrUqYRBodIIwUHgNUdp58st+Ue4bDRX81H/S8fl8XvZ2C1Kp3MkgGMhWPi+rq6tS/vlTlchls3JweCA/flyrcZlMRjX3nqG6W9hRFHQ6XUUGxqAPuuzvF+XmpqI6crhWuxshFOOnCQ/DeOTB12kYReKp616SMn++P+KjQRnT5PPpsfDkXRs/+ZxIwMl4ubOzswhme3t7sr6+/mmxPksxVyqVIixF+c+crDMNaLfbFuHEvd9oNOT6+lqr2/b2tvInF46OjhJzlut0OqkZQOKRXxCJT0ISbarYa/iO40FXLpejarUqKysrmtUILBaLWgV6vZ4KQxE8d3h4uJSMp6cnnSDhCf92u62/Dw4OdI5Jglyr1dIkNuK3Ka016LmacE/r/xJkETCvm5xEI5AmhGhFLi8vNZI7OzvamjBhFgoFjUyn05H9/X3Z3d1VSGEgMKMiLgox12w2U8uBIAjGsKHC9fv90USWy2lOGLS4NiI6k9dvBdyFYZiKAVQePIqilOjRbJs8aQ4kz3bE0WCRFn+VwUTGD0K3ubmZqKfAPhWOM1XMIEQ+QOQDkdnY2Fi6QJhTXK1WUwMMm8tWmlneBd8clGPtcn1fyAnkYAzwQnnkkR+LJu20PPeihiYYaxSH8LrVf+YCjLB5hXeIhkUkjvhxDhhe43pilvDpOcai/R9PvtLRLmKQY0k5yZQ8SIqoRPRDeB3vMzNrX5/N6gGUIIyMmweuXq+PqxDeR9B7yfCPYiQw17owCQJVFtyTE5PdL3LjRN8FQZB4GQX3eB+lLFHf65RZ493Dw8MLCFlIJ71hOJ720DyPxfFmHCPd1dVVRJgJJx0i/QmhBp+E3bZcCDlrXYMA93nnoxSdGQGSmHJGqFEYY1DSEo37NF7Aweq3dabL9CxxvLvImFRyYBHBSb3zohv9v+EQxyh3e3s7rkJA5DNvI75moBqgO2XOaRJ/OQMGg0Hi80AcKMQdk+quRFyllhnnKpWKQsiWcoskMmW2XC6/aAfocyi5HK+V23l8WSvTI9kGAr+Zi0wn25rhORC3tkM3B8gB6rn1Jm8ZQJtgkxueQmGEQfCwJaQ1iPP4ohBjOeDLfGQLH65RlLzEOWacOcnmItfr9aJlthRtrwgG713n4mlziC14zHCMMsfOg9TSOTBvV3kZ7Nq70/zselE5rnpXjUZ7/aMPFPQ7X4nc9z+/R8FgtODAAJZ3rVZL8YwXDJPADCzatX0EsTDbLhybuB85l7jT01P9wIEinFGgVqvpNUqxUqK355okY8VGHvDM1rYYZ3hm3/O9ubEMAlwa2+tvVbJlFHzr3aWT+C2GH/3cNRoNbSXAbVJ7QmkaQR6WSiXVFai6i4sLnYnBfhIL+jSVt+WuTZzahJ5dnGkEVldWpZAvSMZPZxM2LcPc+d/nUX/Ql1w2J/m1/JcyQD+an1+c6/+VsL16MAacktzgSsv73V5XXPW+qjkQDf/9MB3nc1JaSs7jGw5D+fplNM1vZB8RlX8A2cA2K7BgoqcAAAAASUVORK5CYII=","file_name":"53a165ad-df93-4f60-a57a-e12dcfe5f0b4-2019_01_28-images-Screen Shot 2019-01-28 at 10.42.27 AM.png","projectImageCutline":"My Image"}],
The base64 string you see isn't the image but a thumbnail representation of the image. I have asked for an enhancement to disable saving of base64 encoded image thumbnails based on options to save on space in your model.
Screenshot of my Nuit Blanche application with the dropzone field:
Upload Image Retrieval (Note: this part will vary based on implementation, configuration of Upload API, and requirements for your applications)
After you upload a file you might need to retrieve it as well. Here is an example of how image retrieval works. For retrieval it is important to know\understand how the Upload API has been configured and if the image can be access by the network zone you are in.
For this example we are saving the file to the upload API database and the upload API provides us with a another API to get files saved in its database.
To give you another example: Let's say instead of saving the images to the upload API database we were saving the files to the NAS, in that case there currently there is no API that we can use to get those images. So, we would need to use "websync" to get those images on AWS S3 or come up with another approach to expose them using a web server. To learn more about websync please see: /wiki/spaces/DTSKS/pages/18496668
Continuing with my example: As in the Upload API configuration screenshot in the dependencies section I have allowed anonymous internet user to access my images. This is because my nuit blanche application requires this, in your case you might have a different ACL.
This is a screen shot of my public facing application with the image we uploaded.
As you see in the screenshot my final HTML has this as the image source:
<img class="event-list-image" src="https://maserati.corp.toronto.ca:49097/c3api_upload/retrieve/nuit_blanche/Zi2DZlGoy1yOa5dJGIQJoA" alt="My Image">
My JavaScript QuickMap Configuration app that is used to generate this HTML is doing the following:
It has defined the following property in the QuickMap configuration file.
uploadApiUrl: "https://maserati.corp.toronto.ca:49097/c3api_upload/retrieve/nuit_blanche/",
When the application needs to render the list item it used the uploadApiUrl to built the img tag. The value of uploadApiUrl would need to change per environment.
if (val.projectImages[0]) { projectMainImage = ` <div> <img class="event-list-image" src="${quickMapConfig.uploadApiUrl}${val.projectImages[0].bin_id}" alt="${val.projectImages[0].projectImageCutline}"> <div class="">${val.projectImages[0].projectImageCutline}</div> </div> `; }