I have a mobile phonegap application that has access to the devices camera. I am trying to take a photo and use the addAttachments method to upload the selected captured image. My problem is this method only allows for a input type file as the source. Unfortunately phonegap does not support input file types and I have to upload the captured image directly. Is there a way to add attachments without using the form type input. Any help would be greatly appreciated.
Solved! Go to Solution.
Actually, a jsfiddle might not be appropriate for this use case. Below is some code that may work:
var imageName = "someImageFilename";
var imageFormat = "png";
var arrayBufferView = new Uint8Array(imageAsArrayBuffer);
var blobImg = new Blob([ arrayBufferView ], { type: "image/" + imageFormat });
var formNode = put("form", {
"method": "post",
"enctype": "multipart/form-data"
});
var formData = new FormData(formNode);
formData.append("attachment", blobImg, imageName+"."+imageFormat));
esriRequest({
url: "http://[server]/[instance]/rest/services/[folder]/[name]/FeatureServer/[layerid]/[oid]/addAttachment",
form: formData,
content: { f: "json" },
handleAs: "json"
}).then(lang.hitch(this, function(response){
alert("Attachment Success: " +response.addAttachmentResponse.success)
}), lang.hitch(this, function(error){
console.warn(error);
}));
Hi Isaiah, You are 100% correct the ArcGIS API for JavaScript requires a form node to achieve adding attachments. It sounds like you may be implementing something like Phone Gap. Since I am not all that knowledgeable with Phone Gap what could we do different?
Thinking more about this you may just want to set up a related table (not enable attachments). Then upload items to ArcGIS Online using addItem and then store off the item id or item url into the related table. Please if you have time, share recommendations regarding how you would want addAttachment to work or how it could be different.
-Doug
Doug,
Thanks for your reply. Yes I am using Phone Gap to build this application. The issue with Phone Gap is that it does not support input file type. It relies on its plugins to access the file system and camera. This wouldn't be an issue except for the addAttachments only taking a form node. One possible solution that comes to mind is creating a second method that works similar to the old Flex API's addAttachment. This would allow you to send a base64-encoded string as the argument and would then get encoded to an image. Or just simply allow the addAttachments method to accept a direct URL to an image file. Both of these would allow for a more versatile and universally useful addAttachments method.
Unfortunately because of other applications we have set up for viewing these attachments I would not be able to use your suggestion of using related tables. I do however appreciate the help. Is there any other work around you can think of that I could use to add an attachment. Like I mentioned earlier I can either produce a base64-encoded string of the image or I can access the image directly I just cannot use the input file type.
Thanks,
Isaiah Aguilera
Isaiah, depending on how you get the 'image' we might be able to do this.
If you setup a small jsfiddle with a test service we might be able to try some of this out...
Actually, a jsfiddle might not be appropriate for this use case. Below is some code that may work:
var imageName = "someImageFilename";
var imageFormat = "png";
var arrayBufferView = new Uint8Array(imageAsArrayBuffer);
var blobImg = new Blob([ arrayBufferView ], { type: "image/" + imageFormat });
var formNode = put("form", {
"method": "post",
"enctype": "multipart/form-data"
});
var formData = new FormData(formNode);
formData.append("attachment", blobImg, imageName+"."+imageFormat));
esriRequest({
url: "http://[server]/[instance]/rest/services/[folder]/[name]/FeatureServer/[layerid]/[oid]/addAttachment",
form: formData,
content: { f: "json" },
handleAs: "json"
}).then(lang.hitch(this, function(response){
alert("Attachment Success: " +response.addAttachmentResponse.success)
}), lang.hitch(this, function(error){
console.warn(error);
}));
John,
Thank you a ton for your response this is starting to get me to think this might work! I had to ditch the base64 because of performance issues and went with a direct reference to the file. So I had to convert the FILE URI returned from the device Camera into a file object and from there was able to use a FileReader to convert the object to an arraybuffer to use with your provided sample.
var reader = new FileReader();
var arrayBuffer;
window.resolveLocalFileSystemURI(fileURI, function (entry) {
entry.file(function (s) {
arrayBuffer = reader.readAsArrayBuffer(s);
}, function (e) {
console.log('ee');
});
});
var imageName = "someImageFilename";
var imageFormat = "jpeg";
var arrayBufferView = new Uint8Array(arrayBuffer);
var blobImg = new Blob([arrayBufferView], {
type: "image/" + imageFormat
});
This worked great. I am however having issues with creating a form node. Your sample uses var formNode = put(... but I am unsure of where the "put" comes from. Is this a dojo method? I might just be tired and missing this but any clarification would be great. Thanks!
Load the "put-selector/put" module. You can also use dom-construct or any other way of creating a dom node.
John
John,
Your help was invaluable in getting this done! It is now working beautifully and I am very grateful! The hardest part was getting the actual file converted into a blob but I was able to do so with the below code I am posting to help anyone else with this issue.
function onSuccess(fileURI) {
window.resolveLocalFileSystemURL(fileURI, function (entry) {
var reader = new FileReader();
reader.onloadend = function (evt) {
var imageName = "someImageFilename";
var imageFormat = "jpg";
var arrayBufferView = new Uint8Array(evt.target.result);
var blobImg = new Blob([arrayBufferView], {
type: "image/jpeg"
});
var formNode = put("form", {
"method": "post",
"enctype": "multipart/form-data"
});
var formData = new FormData(formNode);
formData.append("attachment", blobImg, imageName + "." + imageFormat);
console.log("worked");
esriRequest({
form: formData,
content: {
f: "json"
},
handleAs: "json"
}).then(lang.hitch(this, function (response) {
console.log("Attachment Success: " );
}), lang.hitch(this, function (error) {
console.warn(error);
}));
};
entry.file(function (s) {
reader.readAsArrayBuffer(s);
}, function (e) {
console.log('Error');
});
});
Once other thing that is not a huge issue but the
response.addAttachmentResponse.success
function you had in the success call for addAttachment was coming back undefined. This didn't effect the actual addAttachment function though so I just removed it. Not sure if there was a typo or something. Anyways thank you for your help!
John passing on my thanks as well. I was not aware of these two JavaScript classes, nor would of seen the context on how they are helpful for uploading files. This was a good post.
Blob - Web API Interfaces | MDN
-Doug
I just wish to express my thanx as well, this discussion helped me incredibly.