Yesterday I failed to get images to upload as CouchDB document attachments using couchapp. This should be do-able given that the Futon administration interface can do it. Just how easy it is remains to be seen...
...which turns out to be fairly easy!
I borrow code from two of CouchDB's javascript libraries:
futon.browse.js—defines how the Futon interface submits its file upload formjquery.dialog.js—attaches actions to futon dialogs like the one that uploads files
upload.html template:<script src="/_utils/script/json2.js"></script>Piece by piece, this function disables normal form submission so that
<script src="/_utils/script/jquery.js?1.2.6"></script>
<script src="/_utils/script/jquery.couch.js?0.8.0"></script>
<script src="/_utils/script/jquery.form.js?0.9.0"></script>
<script src="<%= asset_path %>/vendor/couchapp/jquery.couchapp.js"></script>
<script type="text/javascript" charset="utf-8">
$("#recipe-upload").submit(function(e) { // invoke callback on submit
e.preventDefault();
var data = {};
$.each($("form :input").serializeArray(), function(i, field) {
data[field.name] = field.value;
});
$("form :file").each(function() {
data[this.name] = this.value; // file inputs need special handling
});
if (!data._attachments || data._attachments.length == 0) {
alert("Please select a file to upload.");
return;
}
$(this).ajaxSubmit({
url: "/<%= dbname %>/<%= docid %>",
success: function(resp) {
$('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();
}
});
});
</script>
ajaxSubmit() can be used instead:e.preventDefault();Next it assembles all of the data in the form into a Javascript object:
var data = {};
$.each($("form :input").serializeArray(), function(i, field) {
data[field.name] = field.value;
});
$("form :file").each(function() {
data[this.name] = this.value; // file inputs need special handling
});After checking to see if the data has an empty file upload field, it performs an ajaxSubmit using the current DB and document ID (as supplied by the show function) and defines a simple on-success callback function: $(this).ajaxSubmit({
url: "/<%= dbname %>/<%= docid %>",
success: function(resp) {
$('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();
}
});To test this out, I create an empty "test" document (more precisely I use this document from yesterday):
Then, I access the upload show function for the test document (http://localhost:5984/eee/_design/relax/_show/upload/test) and upload my favorite avatar image:

The "Saved" animation shows, which leads me to believe that the image has been successfully uploaded. To make sure, I check the document again:

Sure enough, the image is now attached to the CouchDB test document. Yay!
There is still some more that I would do if I wanted this to be ready for every day use—links back to the main edit page, an automatic redirect after upload, etc.—but that is good enough for today. I am just happy to know that it is possible with relatively little effort.
Day #25
Small addition to a truly purposefull and informative blog entry. This tells the user that the update has failed- firebug console message of success and fail
ReplyDelete(these messages are within pre tags which are not allowed in your blog comments)
{"ok":true,"id":"test","rev":"25-1223e10f2bd556a67665bc9a0ebae738"}
{"error":"conflict","reason":"Document update conflict."}
$(this).ajaxSubmit({
url: "/<%= dbname %>/<%= docid %>",
success: function(resp) {
if(resp.match("ok")){ $('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();}
else if(resp.match("error")){ $('#failed').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();}
}
This is not working for me. I get the error: '{"error":"method_not_allowed","reason":"Only DELETE,GET,HEAD,PUT allowed"}'. Here is my entire html document which I put on couchdb.
ReplyDeleteI was however forced to remove the usual HTML brackets because HTML is not allowed in comments for some reason.
html
head
script src="http://code.jquery.com/jquery-1.8.2.min.js"/script
script src="http://localhost:5984/_utils/script/jquery.js?1.2.6"/script
script src="http://localhost:5984/_utils/script/jquery.couch.js?0.8.0"/script
script src="http://localhost:5984/_utils/script/jquery.form.js?0.9.0"/script
/head
body
form method="post"
input type="file" id="recipe-upload"
input type="submit"
/form
script type="text/javascript" charset="utf-8"
$("#recipe-upload").submit(function(e) { // invoke callback on submit
e.preventDefault();
var data = {};
$.each($("form :input").serializeArray(), function(i, field) {
data[field.name] = field.value;
});
$("form :file").each(function() {
data[this.name] = this.value; // file inputs need special handling
});
if (!data._attachments || data._attachments.length == 0) {
alert("Please select a file to upload.");
return;
}
$(this).ajaxSubmit({
url: "/%= dbname %/%= docid %",
success: function(resp) {
$('#saved').fadeIn().animate({ opacity: 1.0 },3000).fadeOut();
alert("success");
}
});
});
/script
/body
/html
'
Here is a very simple example with good comments that you can load into your CouchDB. https://gist.github.com/4074427
ReplyDelete