将上传的img保存到localStore并在刷新页面上渲染

问题描述 投票:0回答:1

我需要将图像保存在本地存储中,当页面刷新时它们不会消失而是保留在我的卡中。

上传内容组件:

import React, { useState } from 'react';
import { PlusOutlined } from '@ant-design/icons';
import { Image, Upload } from 'antd';
import type { GetProp, UploadFile, UploadProps } from 'antd';

type FileType = Parameters<GetProp<UploadProps, 'beforeUpload'>>[0];

interface UploadContentProps {
    imageUrl: string; // Define the props that UploadContent component needs
}

const getBase64 = (file: FileType): Promise<string> =>
    new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => resolve(reader.result as string);
        reader.onerror = (error) => reject(error);
    });

const UploadContent: React.FC<UploadContentProps> = ({ imageUrl }) => {
    const [previewOpen, setPreviewOpen] = useState(false);
    const [previewImage, setPreviewImage] = useState('');
    const [fileList, setFileList] = useState<UploadFile[]>([
    ]);

    const handlePreview = async (file: UploadFile) => {
        if (!file.url && !file.preview) {
            file.preview = await getBase64(file.originFileObj as FileType);
        }

        setPreviewImage(file.url || (file.preview as string));
        setPreviewOpen(true);
    };

    const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) =>
        setFileList(newFileList);

    const uploadButton = (
        <button style={{ border: 0, background: 'none' }} type="button">
            <PlusOutlined />
            <div style={{ marginTop: 8 }}>Upload</div>
        </button>
    );
    return (
        <>
            <img src={imageUrl} alt="Uploaded" style={{maxWidth: '100%'}}/>
            <Upload
                action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
                listType="picture-circle"
                fileList={fileList}
                onPreview={handlePreview}
                onChange={handleChange}
            >
                {fileList.length >= 1 ? null : uploadButton}
            </Upload>
            {previewImage && (
                <Image
                    wrapperStyle={{display: 'none'}}
                    preview={{
                        visible: previewOpen,
                        onVisibleChange: (visible) => setPreviewOpen(visible),
                        afterOpenChange: (visible) => !visible && setPreviewImage(''),
                    }}
                    src={previewImage}
                />
            )}
        </>
    );
};

export default UploadContent;


ContentCustom Component:


import React, { useState, useEffect } from "react";
import { Layout, Card, Input, Button, DatePicker, Row, Col } from "antd";
const { Content } = Layout;
import ProfileContent from "../../ProfileContent.tsx";
import UploadContent from "../../UploadContent.tsx";
import moment from "moment";
import { DeleteOutlined  } from "@ant-design/icons";


interface ContentCustomProps {
    selectedMenuKey: string;
}

interface CardData {
    id: number;
    input1: string;
    input2: string;
    input3: string;
}

const ContentCustom: React.FC<ContentCustomProps> = ({ selectedMenuKey }) => {
    const [input1, setInput1] = useState<string>("");
    const [input2, setInput2] = useState<string>("");
    const [input3, setInput3] = useState<string>("");
    const [cards, setCards] = useState<CardData[]>([]);


    // La încărcarea componentei, încarcă cardurile salvate din localStorage
    useEffect(() => {
        const savedCards = localStorage.getItem("cards");
        if (savedCards) {
            setCards(JSON.parse(savedCards));
        }
    }, []);

    const handleInputChange = (_name: string, value: string) => {
        if (_name === "input1") {
            // Allow only alphabetic characters for "Name"
            setInput1(value.replace(/[^a-zA-Z ]/g, ""));
        } else if (_name === "input2") {
            // Allow only numeric characters for "Tel.nr"
            setInput2(value.replace(/[^0-9]/g, ""));
        } else if (_name === "input3") {
            setInput3(value);
        }
    };

    const handleAddCard = () => {
        const newCard: CardData = {
            id: Date.now(),
            input1,
            input2,
            input3,
        };
        const newCards = [...cards, newCard];
        setCards(newCards);
        // Salvare carduri în localStorage
        localStorage.setItem("cards", JSON.stringify(newCards));
        // Reset input values after adding the card
        setInput1("");
        setInput2("");
        setInput3("");
    };


    const handleDeleteCard = (id: number) => {
        const updatedCards = cards.filter(card => card.id !== id);
        setCards(updatedCards);
        localStorage.setItem("cards", JSON.stringify(updatedCards));
    };


    return (
        <Content className={'Content'}  style={{height:559,maxHeight:1500}} >
            {selectedMenuKey === "1" && (
                // Content for "Profile"
                <div>
                    <ProfileContent data={{
                        field1: "Andriuta Dragos",
                        field2: 20,
                        field3: true,
                        field4: ["CR-221"],
                        field5: 10000,
                        field6: new Date(),
                        field7: "Excalibur"
                    }} />
                </div>
            )}
            {selectedMenuKey === "2" && (
                <div>
                    <h2>Cards details</h2>
                    <Row gutter={[40, 40]}>
                        {cards.map(card => (
                            <Col key={card.id} xs={24} sm={12} md={12} lg={12} xl={12}>
                                <Card className={'CardContent'} title="Info about my friend">
                                    <Row align="middle">
                                        <Col xs={16} sm={18} md={18} lg={18} xl={13}>
                                            <p>{`Name: ${card.input1}`}</p>
                                            <p>{`Tel.nr: ${card.input2}`}</p>
                                            <p>{`Date of birth: ${card.input3}`}</p>
                                        </Col>
                                        <Col xs={8} sm={6} md={6} lg={6} xl={6} className={'CardImage'}>

                                            // Here I use Component for Upload img.
                                            <UploadContent onImageUploaded={handleAddCard} />
                                        </Col>
                                    </Row>
                                    <div style={{textAlign: "right"}}>
                                        <DeleteOutlined onClick={() => handleDeleteCard(card.id)}
                                                        style={{color: "darkgray", cursor: "pointer"}}/>
                                    </div>
                                </Card>
                            </Col>
                        ))}
                    </Row>
                </div>
            )}
            {selectedMenuKey === "3" && (
                // Content for "Data"
                <div>
                    <Row>
                        <Col style={{paddingRight:150}} span={12}>
                            <h2>New Card</h2>
                            <Input
                                className="custom-input"
                                name="input1"
                                value={input1}
                                onChange={(e) => handleInputChange("input1", e.target.value)}
                                placeholder="Name"
                            />
                            <Input
                                className="custom-input"
                                name="input2"
                                value={input2}
                                onChange={(e) => handleInputChange("input2", e.target.value)}
                                placeholder="Telefon number"
                            />
                            <DatePicker
                                className="custom-input"
                                name="input3"
                                value={input3 ? moment(input3) : null}
                                onChange={(_date: moment.Moment | null, dateString: string | string[]) => {
                                    if (typeof dateString === "string") {
                                        setInput3(dateString);
                                    }
                                }}
                                placeholder="Date of brith"
                            />

                            <Button type="primary" onClick={handleAddCard}>
                                Add Card
                            </Button>
                        </Col>
                    </Row>
                </div>
            )}
        </Content>
    );
};

export default ContentCustom;

我尝试这样做,但我只是将其放入本地存储中,但无法在刷新页面上获取它,因此我在不使用本地存储时重置项目。

javascript reactjs file-upload local-storage
1个回答
2
投票

实现所需任务的一种方法是对图像 blob 进行字符串化并将其设置为 localStore。

// to store image
localStorage.setItem(localStorageKey, JSON.stringify(imageData));

// to retrieve image
imageData = JSON.parse(localStorage.getItem(localStorageKey))

注意:在基于 Chromium 的浏览器中最大存储限制为 10MB。

另一种方式:

这是js代码示例

读取和存储图像

const reader = new FileReader();
reader.onloadend = () => {
  // convert image to base64 string
  const base64String = reader.result.replace('data:', '').replace(/^.+,/, '');
  // store image
  localStorage.setItem('key::image', base64String);
  // display image
document.getElementById('image').setAttribute('src',`data:image/png;base64,${base64String}`);
};
reader.readAsDataURL(file);

检索图像

const base64String = localStorage.getItem('key::image');
document.getElementById('image').setAttribute('src',`data:image/png;base64,${base64String}`)
© www.soinside.com 2019 - 2024. All rights reserved.