---
title: Custom Previews for File Upload Questions
product: Form Library
description: With SurveyJS form builder tool, you can create custom file previews for File Upload questions. This free demo for JavaScript offers a step-by-step guide on how to override the built-in preview functionality by adjusting the showPreview property and how to render personalized previews using the onAfterRenderQuestion event handler. 
framework: React
source: https://surveyjs.io/form-library/examples/custom-file-previews/reactjs
index: https://surveyjs.io/form-library/examples/overview.md
---

# Custom Previews for File Upload Questions (React)

SurveyJS File Upload questions support the file preview functionality out of the box (see the [File Upload](/form-library/examples/file-upload/) demo). This example demonstrates how you can override this functionality and implement custom file previews if required.

To implement custom file previews, follow the steps below:

1. Disable built-in file previews.      
Set the File Upload question's [`showPreview`](/form-library/documentation/api-reference/file-model#showPreview) property to `false`.

1. Implement a custom file preview component.       
In this demo, a custom component adds a `<div>` element to the bottom of the question. When users select one or multiple files for upload, this `<div>` displays "Download file" and "Remove file" buttons per uploaded file.

1. Register your custom component under the `sv-file-preview` name.      
    In HTML/CSS/JavaScript projects, register the component in `ReactElementFactory` as shown in the `index.js` file.           
    In React, register the component in `ReactElementFactory` as shown in the `FilePreviewComponent.jsx` file.          
    In Angular, register the component in `AngularComponentFactory` as shown in the `file-preview.component.ts` file.              
    In Vue.js, register the component in `ComponentFactory` as shown in the `main.ts` file.

> In this demo, files are uploaded to SurveyJS servers from where they are then deleted after a predefined period of time. We strongly encourage you to use your own servers for file uploads when you use SurveyJS to collect sensitive respondent data in your application.

## Files

### `public/index.html`

```html
<div id="surveyElement" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; min-height: 100%; height:100%"></div>
```

### `src/FilePreviewComponent.css`

```css
.my-preview-container {
    margin-top: 2em;
    max-width: calc(100% - 64px);
    margin-bottom: 1em;
    padding-left: 1em;
    padding-right: 1em;
    box-sizing: border-box;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 0;
}

.btn {
    appearance: none;
    border: 1px solid lightgray;
    cursor: pointer;
    padding: 4px 8px;
    color: var(--sjs2-color-fg-brand-on-primary, #fff);
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.button-container {
    width: 100%;
    display: flex;
    gap: 8px;
}

.btn--choose {
    background-color: var(--sjs2-color-project-brand-600, #19b394);
    overflow: hidden;
    flex: 1 1 auto;
}

.btn--choose:hover {
    background-color: var(--sjs2-color-bg-brand-primary-dim, rgb(20, 164, 139));
}

.btn--remove {
    background-color: var(--sjs2-color-bg-alert-primary, #e60a3e);
}

.btn--remove:hover {
    background-color: rgb(217, 4, 49);
}
  
```

### `src/FilePreviewComponent.jsx`

```js
import { createElement } from "react";
import "./FilePreviewComponent.css";
import { SurveyElementBase, ReactElementFactory } from "survey-react-ui";

class FilePreviewComponent extends SurveyElementBase {
    constructor(props) {
        super(props);
        this.state = {
            question: props.question
        };
    }
    downloadFile = (fileItem) => {
        fetch(fileItem.content)
            .then((response) => response.blob())
            .then((blob) => {
                const file = new File([blob], fileItem.name, {
                    type: fileItem.type
                });
                const reader = new FileReader();
                reader.onload = (e) => {
                    const a = document.createElement("a");
                    a.href = e.target.result;
                    a.download = fileItem.name;
                    a.click();
                };
                reader.readAsDataURL(file);
            })
            .catch((error) => {
                console.error("Error:", error);
            });
    };

    render() {
        const { question } = this.state;
        if (!question || !question.value) {
            return null;
        }
        const isReadOnly = question.isReadOnly || (question.survey && question.survey.readOnly);
        return (
            <div className="my-preview-container">
                <div className="files-container">
                    {question.value.map((fileItem) => (
                        <div className="button-container" key={fileItem.name}>
                            <div
                                className="btn btn--choose"
                                onClick={() => this.downloadFile(fileItem)}
                            >
                                {"Download " + fileItem.name}
                            </div>
                            <div
                                className={`btn btn--remove ${isReadOnly ? 'disabled' : ''}`}
                                onClick={() => !isReadOnly && this.state.question.removeFile(fileItem.name)}
                                title="Remove file"
                                style={{ cursor: isReadOnly ? 'not-allowed' : 'pointer', opacity: isReadOnly ? 0.5 : 1 }}
                            >
                                {"X"}
                            </div>
                        </div>
                    ))}
                </div>
            </div>
        );
    }
}

ReactElementFactory.Instance.registerElement("sv-file-preview", (props) => {
    return createElement(FilePreviewComponent, props);
});
```

### `src/SurveyComponent.jsx`

```js
import React from "react";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";
import "survey-core/survey-core.min.css";
import "./index.css";
import { json } from "./json";
import "./FilePreviewComponent";

function SurveyComponent() {
    const survey = new Model(json);
    survey.onComplete.add((sender, options) => {
        console.log(JSON.stringify(sender.data, null, 3));
    });
    survey.onUploadFiles.add((_, options) => {
        const formData = new FormData();
        options.files.forEach((file) => {
            formData.append(file.name, file);
        });
    
        fetch("https://api.surveyjs.io/private/Surveys/uploadTempFiles", {
            method: "POST",
            body: formData
        })
            .then((response) => response.json())
            .then((data) => {
                options.callback(
                    options.files.map((file) => {
                        return {
                            file: file,
                            content: "https://api.surveyjs.io/private/Surveys/getTempFile?name=" + data[file.name]
                        };
                    })
                );
            })
            .catch((error) => {
                console.error("Error: ", error);
                options.callback([], [ "An error occurred during file upload." ]);
            });
    });
    async function deleteFile(fileURL) {
        try {
            const name = fileURL.split("=")[1];
            const apiUrl = `https://api.surveyjs.io/private/Surveys/deleteTempFile?name=${name}`;
            const response = await fetch(apiUrl, { method: "DELETE" });
    
            if (response.status === 200) {
                console.log(`File ${name} was deleted successfully`);
                return "success";
            } else {
                console.error(`Failed to delete file: ${name}`);
                return "error";
            }
        } catch (error) {
            console.error("Error while deleting file: ", error);
            return "error";
        }
    }
    
    survey.onClearFiles.add(async (_, options) => {
        if (!options.value || options.value.length === 0) {
            return options.callback("success");
        }
    
        const filesToDelete = options.fileName
            ? options.value.filter((item) => item.name === options.fileName)
            : options.value;
    
        if (filesToDelete.length === 0) {
            console.error(`File with name ${options.fileName} is not found`);
            return options.callback("error");
        }
    
        const results = await Promise.all(
            filesToDelete.map((file) => deleteFile(file.content))
        );
    
        if (results.every((res) => res === "success")) {
            options.callback("success");
        } else {
            options.callback("error");
        }
    });
    return (<Survey model={survey} />);
}

export default SurveyComponent;
```

### `src/index.css`

```css
/* You can add your custom CSS here. */
```

### `src/index.js`

```js
import React from "react";
import { createRoot } from "react-dom/client";
import SurveyComponent from "./SurveyComponent";

const root = createRoot(document.getElementById("surveyElement"));
root.render(<SurveyComponent />);
```

### `src/json.js`

```js
export const json = {
  "elements": [
    {
      "type": "file",
      "title": "Please upload your files",
      "name": "files",
      "storeDataAsText": false,
      "allowMultiple": true,
      "showPreview": false,
      "maxSize": 102400
    }
  ]
};
```

### `src/theme.js`

```js
export const themeJson = {};
```

### `package.json`

```json
{
  "dependencies": {
    "react": "latest",
    "react-dom": "latest",
    "babel": "latest",
    "survey-core": "latest",
    "survey-react-ui": "latest"
  },
  "devDependencies": {
    "react-scripts": "latest"
  }
}
```

## Other Frameworks

- [Angular](https://surveyjs.io/form-library/examples/custom-file-previews/angular.md)
- [Vue 3](https://surveyjs.io/form-library/examples/custom-file-previews/vue3js.md)
- [jQuery](https://surveyjs.io/form-library/examples/custom-file-previews/jquery.md)
- [Vanilla JS](https://surveyjs.io/form-library/examples/custom-file-previews/vanillajs.md)
