How can I automatically show documents that have been uploaded by site "visitors"?

Basically, I’m building a simple site that should allow a few designated users to upload documents onto a site page, so that other visitors can then view and/or download these files. I don’t like the dropbox/google-drive apps for sharing folders, and would much rather display these uploaded files as document buttons on a grid, in a table of downloadable documents, or some other user-friendly format.
I’ve added a dataset, an upload button, and a submit button to a password-protected page on my site, but I’m very new to this all, so I have a few questions:

  1. I can see that files have been uploaded via the dataset manager, but they appear as empty (yet enumerated) rows. No file name, no extra info, nothing recognizable at all. I only know these are the uploaded files because the enumeration goes up in accordance to my playing around and uploading files.
  2. How do I display these documents on a page of choice?? I tried many things but couldn’t get anything to work. Is this something I’ll need to do programmatically? If so, where do I begin?

Thanks a-million!

Hi :raised_hand_with_fingers_splayed:

One solution that I always use is making an object field in the database, then when uploading the file (using code), I take the file name, size, the video length, the video/image width and height along with the uploaded file url and store them all in one field.

Here’s a tip for uploading any file and get all of its data:

// The initial state of the object
let file = {
    name: null, // String
    size: null // Number
}
const pending_file = $w("#myUploadButton").value[0];

// Get the file name
image.name = pending_file.name;

// Get the file
image.size = pending_file.size / 1e+6 // Converting the size to MBs.

let uploadedFile = await $w("#myUploadButton").startUpload().then((result) => {
    return result;
}).catch(() => {
    return null;    
})

if (uploadedFile) {
    /* Once the file is uploaded, we can extract the data from it.
    we get all the keys of the file and store them */
    
    // Get the keys:
    const keys = Object.keys(uploadedFile);
    if (keys.length > 0) {
        // Once we have the keys, we'll loop through them and add them to our object
        for (let i = 0; i < keys.length; i++) {
            let propName = keys[i];
            if (uploadedFile[propName]) {
                file[propName] = uploadedFile[propName];
            }
        }
    }
    
    /* Another way is to get the uploaded file object and add the name and the size to it normally like this */
    uploadedFile.name = file.name;
    uploadedFile.size = file.size;
    
    // But only use one of them, you don't need both
}
 

Then save the “file” object into the database in the object field.

Hope this helps~!
Ahmad

Wow! Thanks @ahmadnasriya ! I assume my question is rather dumb, but as I said, I’m new to this…So a simple follow-up question - Under which function should this kind of code snippet go? I see there’s an asynchronous “await” so I’m assuming this should go under the scope of an asynchronous method?
Also - how do I then display these documents for other visitors to access?
Thanks again!

@forautozoom3125 It should be inside the event handler function, for example the onClick( ) event handler, and it’ll look something like this.

$w('#button').onClick(async (event) => {
    // The code goes here
})

Use the orange keyword async to change the function into an async function.

To display the files, for example on a dynamic page or in a repeater, you just need to access the data object, and set the file URL as the link of a button, and the file name as a text element.

Assuming that you want to display them on a dynamic page, and that the field you used to store the file object is called “file”.

let data = $w('#dataset').getCurrentItem();

// Configure the text
$w('#fileName').text = data.file.name;

// Configure the button
$w('#downloadFile').target = '_blank'; // Open the link in a new tab
$w('#downloadFile').link = data.file.url;

Some of the APIs that I used:
getCurrentItem( ), link, target, text. the upload button APIs.

Hope this helps.

@ahmadnasriya This definitely helps! I’ll plod through the learning process with your invaluable pointers and tips, and hopefully in a week or so I’ll be able to announce success :wink:

@forautozoom3125 I’m glad that you find it useful, and I’ll be glad to help you through your journey, just tag me in your post and I’ll assist you as much as I can :wink: Please let us know when you successfully finish it.

@ahmadnasriya Hi Ahmad!
I’ve made progress on many fronts, and I’m going about it in a slightly different way than what you recommended, but there’s one point that’s still alluding me.
Basically, the pending file (i.e $w( “#uploadButton1” ).value[ 0 ]) has the main property that I want, namely the file name.
So the easiest thing to do would be to run a wixData.update method, so as to write-in the information I want into the designated column.
However, this would require knowing the item’s id, and that seems to be unavailable. It’s available in a pre-upload hook I added, but the file name and wix-url are not available in the hook, so I’m back to square 1…
Is the item’s id available post-uploading?
I can attach some of my code if that helps…

(Alternatively, can I pass the file-name into the beforeInsert hook? I can easily use that in order to create a solution…)

Damn-it! I’ve finally got it to do what I want (I added a query taking the newest item, obtained the _id, and used that for an update command), only to find out that the intra-wix so-called “url” is not a valid linkable url at all!!
Is there any way to get an item’s actual downloadable valid url??
The whole point (as described in original post) is to allow a user to upload files, and other visitors to subsequently download these files. How can that be obtained?
Thanks