Implementing File Input By Copy-Paste on the Web
Tags: webdev, frontend, javascript
Published: 2024-07-17 11:54:04

In the sphere of web development, there are multiple ways to upload files when collecting user input. One of the methods is copy-paste. Copy-paste for file input is a very intuitive method of uploading files from users. Copy-paste file input method relieves users of the need to memorize the location of the file they want to upload. In this article, we will discuss how you can implement file input by copy-paste on your website.

We will implement the copy-paste file input by taking advantage of the `ClipboadEvent`  and the `EventTarget` interfaces. The `ClipboardEvent` interface provides information about the `paste` event, and the `EventTarget` interface allows us to listen to the paste event.

While listening to the paste event, we will attach an event handler function where we decide what to do with the pasted items. In our case, we will take the pasted file and render it instantly after it is completely loaded into the browser. We will begin with the HTML and the styles.

## The HTML and the Styles
Let us start by creating the HTML markup of the paste area. The code snippet below is the HTML markup:
```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Copy-Paste File Input</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div 
        id="pasteArea" 
        contenteditable="true" 
        style="border: 2px dashed #ccc; padding: 20px;"
    >
        Paste your file here
    </div>
    <div id="preview"></div>
    <script src="script.js"></script>
</body>
</html>
```

The code snippet above renders a rectangular container within which we will be able to paste files. The container has an attribute called `contenteditable` set to `true`. The `contenteditable` attribute is important to enabling the pasting of files or any other items in the container. If the `contenteditable` attribute is changed to `false` or removed, the `paste` action will not work as expected. We also have a container with the id of `preview`. We will use the preview container to preview the image pasted by the user.


Let's add a few basic styles to our markup from `style.css`

```
*{
    font-family: Arial, Helvetica, sans-serif;
}

body{
    text-align: center;
    margin-block-start: 4rem;
}
#pasteArea {
    border: 2px dashed #ccc;
    padding: 20px;
    width: 300px;
    height: 200px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    cursor: pointer;
    margin: auto;
    color: rgb(5, 89, 89);
}

#preview img {
    max-width: 100%;
    margin-top: 10px;
}
```

The above markup and style sheet creates a simple dash-bordered container with a simple prompt text as shown in the screenshot below:

![Paste Container](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ewg9ctw0ls6kbzbwkuco.png)

Now that we have created the UI, let us add some useful functionalities with JavaScript in the next section.

## The Script
In this section, we will use JavaScript to add a `paste` event listener to the paste area. Before we get the paste area from the DOM to attach the event listener, we first wait for the DOM content to be loaded as in the code snippet below.

```
document.addEventListener('DOMContentLoaded', () => {
    const pasteArea = document.querySelector('#pasteArea');
    
    pasteArea.addEventListener('paste', (event) => {
        
    });
});
```

In the code snippet above, we have added a listener for the `DOMContentLoaded` event. This allows us to wait for the DOM tree to be created before we can get the DOM elements. Next, we select the paste area container and append a `paste` event listener to it. 



##### Getting the file from the pasted items
The `paste` event handler was left unimplemented in the previous code snippet. Let's implement it by getting the data from the event object and logging them in the console. We will do more with the data later in the article, for now, we just want to ensure that the files are received when items are pasted in the paste area. The code snippet below shows the minimal implementation of the `paste` event handler.

```
pasteArea.addEventListener('paste', (event) => {
        const items = event.clipboardData.items
        for (const item of items) {
            if (item.kind === 'file') {
                const file = item.getAsFile()

                console.log(file)
            }
        }
    })
```

In the code snippet above, we get items from the `event.clipboardData` object. The `event.clipboardData.items` is a `DataTransferItemList` which is a list-like object containing the content of the pasted items. The items are stored in a list because it is possible for a user to copy and paste multiple items at once. 

Next, we iterate over the items using the `for ...of` loop. In the loop, we check if each of the items is a file. If the item is of king 'file', we get it as a file and print it on the browser's console.

Printing the file information on the console is not very useful to the users of your web page. Let's do something a little more interesting in the next section.



##### Previewing the uploaded file
It would be hard for a user to know that the file upload was successful after pasting the items for the clipboard if we don't show it anywhere. It is important to indicate that the file was successfully uploaded by displaying something that indicates success. What better way to indicate the success of an upload than displaying the uploaded file itself? 

In this section, we will extend the `paste` event handler to create a URL from the received file. We will use the created URL to render the file once it's loaded into the browser. We will take advantage of the `FileReader` API to create a URL from the file as coded in the snippet below.

```
pasteArea.addEventListener('paste', (event) => {
        const items = event.clipboardData.items
        for (const item of items) {
            if (item.kind === 'file') {
                const file = item.getAsFile()

                
                const reader = new FileReader();
                
                reader.onloadend = (e) => {
                    const url = e.target.result
                    console.log(url)

                };
                reader.readAsDataURL(file);
            }
        }
    });
``` 

In the code snippet above, we have created an instance of the `FileReader` and used it to generate the data URL. We have also appended a `loadend` event listener to the `FileReader` object where we log the the result of the reading to the console. This is the first step towards previewing the file, we can now use the URL to display the file.

Assuming the user pasted image files, the following code snippet shows how we can extend the event handler to create a URL and display the image file.

```
 reader.onloadend = (e) => {
       const url = e.target.result
       const preview = document.querySelector('#preview')
       const img = document.createElement('img');

       img.src = url;
       preview.appendChild(img);
   };
```

In the code snippet above, we get the preview container from the DOM and create an `img` element for rendering the image. We assign the created URL as the `src` of the image and append the image to the preview container. Once the image is appended to the preview container, the user can now know that the image they pasted was successfully loaded into the web page.

Success! We have successfully implemented file uploads by copy-paste on a webpage. This method of file upload gives users the privilege of uploading files easily without the need to click several buttons to select the file to be uploaded. The `ClipboadEvent` interface provides an easy way to collect data from items pasted on the browser. The `FileReader` interface allows us to create a URL from the uploaded file and use it to preview the uploaded file. 

Feel free to say something in the comment section. Find more about the [ClipBoardEvent](https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData) and the [FileReader](https://developer.mozilla.org/en-US/docs/Web/API/FileReader) interfaces from MDN.