Forum OpenACS Development: FS pkg: Upload multiple files

Collapse
Posted by Iuri Sampaio on
Hi there,

I have multiple files coming trough file-storage > file-add > form > new_data > fs::add_file

The form filed remained named as upload_file and after submit, its structure is as showed bellow:

upload_file.content-type = image/png
upload_file = logo-flag1.png
upload_file.tmpfile = /tmp/ns-Hzx2ir
upload_file.content-type = image/png
upload_file = logo-flag2.png
upload_file.tmpfile = /tmp/ns-Z8Hie3

Within the TCL file file-add.tcl: the field of the form is still "upload_file (datatype file)" but now it has two or more files

ad_page_contract {..} {...
upload_file:multiple,trim,optional
upload_file.tmpfile:multiple,tmpfile,optional
inside.

However Naviserver complains with the following message:

[22/Mar/2017:18:22:37][1688.7fe85bfff700][-conn:1contact:3-] Warning: User experienced 'You've supplied two values for 'upload_file'' when submitting a form related to path_info:

Thus, I've tried to adapt the script adding the upload_file as a multiple variable. But it doesn't work as expected.

ad_page_contract {..} {...
upload_file:multiple,trim,optional
upload_file.tmpfile:multiple,tmpfile,optional

but such amend overwrote the file contents and part of the files attributes (i.e. content-type and tmp file) are gone. the variable upload_file now has only the filenames

upload_file.content-type = image/png
upload_file = logo-flag1.png
upload_file.tmpfile = /tmp/ns-Hzx2ir
upload_file.content-type = image/png
upload_file = logo-flag2.png
upload_file.tmpfile = /tmp/ns-Z8Hie3

What would be the correct data structure to the variable in order to accept multiple files within it as in the example above?

Best wishes,
Iuri

[22/Mar/2017:18:22:37][1688.7fe85bfff700][-conn:1contact:3-] Warning: User experienced 'You've supplied two values for 'upload_file'' when submitting a form related to path_info:
called from template::adp_parse /var/www/1contact/packages/1c-annonces/www/create-annonce {}
called from adp_parse_ad_conn_file
called from rp_serve_concrete_file /var/www/1contact/packages/1c-annonces/www/create-annonce.adp
called from rp_serve_abstract_file 0 0 .* /var/www/1contact/packages/1c-annonces/www/create-annonce
called from rp_handler
POST http://1c.1contact.ch:8000/annonces/create-annonce? referred by 'http://1c.1contact.ch:8000/annonces/create-annonce'; peer 192.168.0.3 user_id 698
post-data:

Collapse
Posted by Antonio Pisano on
Hello Iuri,

to better understand: can you please post the exact content of the upload_file variable before and after your "multiple" modification?

Also, I would be interested in the exact ad_page_contract of your page (the page variable definition) before and after.

One thing that pops into my mind at the moment could have something to do with the :array flag. Maybe could help.

https://openacs.org/api-doc/proc-view?proc=ad_page_contract&source_p=1

All the best

Collapse
Posted by Iuri Sampaio on
Pisano,

I believe the problem is that I have no clue how to handle variables with the structure "var.var" such as upload_file.tmpfile.

The chunk of code is very similar, if not the same, of file-add.tcl > ad_form > new_data's block.

To get started, I tried to ns_log Notice "$upload_file - $upload_file.tmpfile" within error.log but I had no success except for:


set myform [ns_getform]
if {[string equal "" $myform]} {
ns_log Notice "No Form was submited"
} else {
ns_log Notice "FORM"
ns_set print $myform
for {set i 0} {$i < [ns_set size $myform]} {incr i} {
set varname [ns_set key $myform $i]
set varvalue [ns_set value $myform $i]
if {[string match {cat_*} $varname]} {
#set varname [lindex [split $varname "_"] 1]
#lappend lchars "$varname $varvalue"
}
}
}

TCL's file croate-annonce.tcl: http://pastebin.com/UB9yDxnR
Also error.log is here: http://pastebin.com/GjKEtpqE

Best wishes,

Bellow, it is the error that returns if I remove "multiple" from ad_page_contract headers.

upload_file:multiple,trim,optional
upload_file.tmpfile:mutiple,tmpfile,optional


upload_file:trim,optional
upload_file.tmpfile:tmpfile,optional

[23/Mar/2017:08:36:11][1711.7f2caa548700][-conn:1contact:0-] Warning: User experienced 'You've supplied two values for 'upload_file'' when submitting a form related to path_info:
called from template::adp_parse /var/www/1contact/packages/1c-annonces/www/create-annonce {}
called from adp_parse_ad_conn_file
called from rp_serve_concrete_file /var/www/1contact/packages/1c-annonces/www/create-annonce.adp
called from rp_serve_abstract_file 0 0 .* /var/www/1contact/packages/1c-annonces/www/create-annonce
called from rp_handler
POST http://1c.1contact.ch:8000/annonces/create-annonce? referred by 'http://1c.1contact.ch:8000/annonces/create-annonce'; peer 192.168.0.4 user_id 698
post-data:

[23/Mar/2017:08:36:11][1711.7f2caa548700][-conn:1contact:0-] Warning: User experienced 'You've supplied two values for 'upload_file.tmpfile'' when submitting a form related to path_info:
called from template::adp_parse /var/www/1contact/packages/1c-annonces/www/create-annonce {}
called from adp_parse_ad_conn_file
called from rp_serve_concrete_file /var/www/1contact/packages/1c-annonces/www/create-annonce.adp
called from rp_serve_abstract_file 0 0 .* /var/www/1contact/packages/1c-annonces/www/create-annonce
called from rp_handler
POST http://1c.1contact.ch:8000/annonces/create-annonce? referred by 'http://1c.1contact.ch:8000/annonces/create-annonce'; peer 192.168.0.4 user_id 698
post-data:

[23/Mar/2017:08:36:11][1711.7f2caa548700][-conn:1contact:0-] Warning: User experienced 'You've supplied two values for 'upload_file'' when submitting a form related to path_info:
called from template::adp_parse /var/www/1contact/packages/1c-annonces/www/create-annonce {}
called from adp_parse_ad_conn_file
called from rp_serve_concrete_file /var/www/1contact/packages/1c-annonces/www/create-annonce.adp
called from rp_serve_abstract_file 0 0 .* /var/www/1contact/packages/1c-annonces/www/create-annonce
called from rp_handler
POST http://1c.1contact.ch:8000/annonces/create-annonce? referred by 'http://1c.1contact.ch:8000/annonces/create-annonce'; peer 192.168.0.4 user_id 698
post-data:

[23/Mar/2017:08:36:11][1711.7f2caa548700][-conn:1contact:0-] Warning: User experienced 'You've supplied two values for 'upload_file.tmpfile'' when submitting a form related to path_info:
called from template::adp_parse /var/www/1contact/packages/1c-annonces/www/create-annonce {}
called from adp_parse_ad_conn_file
called from rp_serve_concrete_file /var/www/1contact/packages/1c-annonces/www/create-annonce.adp
called from rp_serve_abstract_file 0 0 .* /var/www/1contact/packages/1c-annonces/www/create-annonce
called from rp_handler
POST http://1c.1contact.ch:8000/annonces/create-annonce? referred by 'http://1c.1contact.ch:8000/annonces/create-annonce'; peer 192.168.0.4 user_id 698
post-data:

[23/Mar/2017:08:36:11][1711.7f2caa548700][-conn:1contact:0-] Notice:

Collapse
Posted by Antonio Pisano on
Dear Iuri,

I could make a toy example for you. Create a page in %server-root%/www/test-form.tcl with this code:

ad_page_contract {
} {
upload_file:multiple,trim,optional
upload_file.content-type:trim,multiple,optional
upload_file.tmpfile:tmpfile,multiple,optional
}

set existing {}
foreach f ${upload_file.tmpfile} {
lappend existing [file exists $f]
}
ns_return 200 text/html "$upload_file -- ${upload_file.tmpfile} -- $existing -- ${upload_file.content-type}"

Then from the /ds/shell test it like this:

set files {
{data aaa filename test.html fieldname upload_file}
{data bbb filename test2.txt fieldname upload_file}
}
array set r [util::http::post -url http://137.208.114.98:8000/test-form -files $files]

set r(page)

As you can see, multiple file uploads will make each variable a list you can loop through in respective order.

Hope this helps

Antonio

Collapse
Posted by Iuri Sampaio on
Thanks a lot Pisano!
You helped me to realize that there's nothing new!

"var.var" is a simple thing and it should the treated as a list. The usage of foreach statement is enough to iterate and catch all multiple values within the variable.

The key was that I should have used the entire name explicitly, as the variable's name (i.e. upload_file.tmpfile).

I was killing myself because I was trying to reach the values,
using only the first part of its name, as in: $upload_file and $upload_file(tmp file). Then, I got lost writing more trash code related to TCL array and etc

Thanks again and Best wishes,
Iuri