0

I got two files for the image upload to a S3 Bucket with react and aws-sdk.

Component File S3 Uploader:

/* S3Uploader.js */
import AWS from "aws-sdk";

const generateUniqueFileName = (originalFileName) => {
    const uniqueId = Date.now().toString(36);
    return `${uniqueId}_${originalFileName}`;
};

const uploadFileToS3 = async (file, bucket) => {
    const uniqueFileName = generateUniqueFileName(file.name);

    const s3 = new AWS.S3({
        accessKeyId: process.env.REACT_APP_AWS_ACCESS_KEY,
        secretAccessKey: process.env.REACT_APP_AWS_SECRET_ACCESS_KEY,
        region: process.env.REACT_APP_AWS_REGION
    });

    const params = {
        Bucket: bucket,
        Key: uniqueFileName,
        Body: file,
        ContentType: file.type
    };

    return s3.upload(params).promise();
};

export default uploadFileToS3;

I use this in a form for upload Images:

/* S3ImageUploadComponent.js */
import React, {useRef, useState} from "react";
import uploadFileToS3 from "./S3Uploader";

const S3ImageUploadComponent = () => {
    const fileInputRef = useRef(null);
    const [selectedFiles, setSelectedFiles] = useState([]);
    const [previewUrls, setPreviewUrls] = useState([]);

    const handleFileSelection = (event) => {
        const files = Array.from(event.target.files);
        setSelectedFiles(files);

        const urls = files.map((file) => URL.createObjectURL(file));
        setPreviewUrls(urls);
    };

    const handleFileUpload = async () => {
        try {

            const uploadPromises = selectedFiles.map((file) => uploadFileToS3(file, "bucketname"));

            await Promise.all(uploadPromises);

            console.log("Files uploaded successfully.");

            // Perform any necessary actions after successful upload
            setSelectedFiles([]);
            setPreviewUrls([]);
            fileInputRef.current.value = null;
        } catch (error) {
            console.error("Error uploading files:", error);
        }
    };

    const handleClearSelection = () => {
        setSelectedFiles([]);
        setPreviewUrls([]);
        fileInputRef.current.value = null;
    };

    const handleNameChange = (event) => {
        setName(event.target.value);
    };

    return (
        <div>
            <form>
                <div>
                    <label>Files:</label>
                    <input type="file" ref={fileInputRef} onChange={handleFileSelection} multiple />
                </div>
                <div>
                    {previewUrls.map((url, index) => (
                        <img
                            key={index}
                            src={url}
                            alt={`Preview ${index}`}
                            style={{maxWidth: "200px", marginRight: "10px"}}
                        />
                    ))}
                </div>
                <button onClick={handleFileUpload} disabled={selectedFiles.length === 0}>
                    Submit
                </button>
                <button onClick={handleClearSelection} disabled={selectedFiles.length === 0}>
                    Clear
                </button>
            </form>
        </div>
    );
};

export default S3ImageUploadComponent;

The upload only works if I set a breakpoint on

await Promise.all(uploadPromises);

I am sitting on this since hours and I can not explain it.

I tried to upload an Image with aws-sdk to a S3 Bucket. The Component itself works, but if i implement this in another file it is only working with a breakpoint set on the return promise.

J.D.
  • 75
  • 7
  • 2
    It looks like the default HTML form submission behavior is occurring when that button is clicked, so the browser is probably reloading the page before the upload can complete. I would try one of the solutions here https://stackoverflow.com/questions/932653/how-to-prevent-buttons-from-submitting-forms – Mark B Jul 09 '23 at 16:30

0 Answers0