React / Node / MongoDB应用程序:如何通过URL链接将图像存储在数据库中

时间:2019-01-25 23:32:02

标签: node.js reactjs mongodb typescript textarea

我在react / typescript应用程序中创建了一个带有textarea组件的表单,您可以在其中将剪贴板中的图像(打印屏幕截图)粘贴到描述字段中。粘贴图像时,您具有粘贴在描述字段中的html代码(例如:http:// localhost:3000 / xxxxx-xxx-xxx-xxx-xxx-xxxxxxxx“ />),并且图像正确显示在我的预览部分。

我的问题是:提交表单时没有保存图像,因为我没有向后端和数据库发送任何信息。但是,我不知道如何将这些粘贴的图像保存到数据库中,因为我只有从事件中检索到的图像URL。网址图片链接应与我从输入事件中检索到的链接相同,以免破坏我的显示。

此外,我使用的是打字稿,因此并非所有npm软件包都可以与我的代码一起使用。

这是我表格的代码:

interface ItemsStates {
    item: ItemModel;
    isSubmitSuccess: boolean;
}


export const ItemCreation = withGlobalContext(
    class extends React.Component<IPropsWithGlobalContext, ItemsStates> {
        constructor(props: any) {
            super(props);

            this.state = {
                item: new ItemModel(),
                isSubmitSuccess: false,
            };
        
            this.handleUserInput= this.handleUserInput.bind(this);
            this.submitForm= this.submitForm.bind(this);

        }
           
    
        handleUserInput(event:any) {
            const { value, name } = event.target;
            const item = {
                ...this.state.item,
                [name]: value,
            };
            this.setState({ item });
        }

    

        submitForm(event:any) {
            event.preventDefault();
            
            const item = this.state.item;

            axios.post(`http://localhost:3000/api/items`, item)
                .then(res => {
                    console.log( "DATA UPLOADED", res);
                    console.log("RES DATA",res.data);
                    this.setState({ isSubmitSuccess: true });
                })
                .catch(err => {
                    console.log("ERROR", err);
                    alert("Sorry! There was an error.");
                  });

            this.setState({ item: new ItemModel() })
            
        }


        render() {
            const { item, isSubmitSuccess } = this.state as any;

            if (isSubmitSuccess) {
                return <Redirect to={`/items`} /> 
            }
            
            return(
                <>
                    <h1>Create new item.</h1>

                    <div>
                    
                        <form onSubmit={this.submitForm}>
                            <div>
                                <label htmlFor="title" >Title</label>
                                <div>
                                    <input type="text" name="title" onChange={this.handleUserInput} value={item.title} />
                                </div>
                            </div>
                            
                            <Textarea onUserInput={this.handleUserInput}  value={item.description} creation={true} />  
                            
                            <div>
                                <label htmlFor="author">Author</label>
                                <div>
                                    <input type="text" name="author" onChange={this.handleUserInput} value={item.author} />
                                </div>
                            </div>
                        </form>
                                
                        <div>
                        <button onClick={this.submitForm}>Submit</button>
                        </div>
                    </div>
                </>
            );
        }
    }
);

这是我的textarea组件的代码:

interface ITextareaProps {
    onUserInput: any;
    value:string;
}

interface ITextareaStates {
    description: string;
}

export const Textarea = withGlobalContext(
    class extends React.Component<ITextareaProps, ITextareaStates> {

        static getDerivedStateFromProps(props:any, state:any) {
            if ( !props.creation && (state.description === "" || state.description === undefined) ) {
                return { description: props.value };
                
            }
            return null;
          }

        constructor(props: any) {
            super(props);

            this.state = {
                description: "",
            };
            
            this.sendUserInput = this.sendUserInput.bind(this);
        }
        

        sendUserInput(event:any) {
            this.setState({
                description: event.target.value,
            });
            this.props.onUserInput(event);    
        }

        handleImagePaste = (dataReceived:any) => {
            for ( const index in dataReceived) {
              if (dataReceived[index].kind === 'file') {
                const blob = URL.createObjectURL(dataReceived[index].getAsFile());
                const balise = `<img src="${blob}" />`;
                this.setState({
                    description: `${this.state.description} ${ balise}`,
                });
              }
              
            }   
          }      
       

      render() {

        return (
          <>
            <div>
                <label htmlFor="description">Description</label>
                <div>
                    <Clipboard handlePaste={this.handleImagePaste}>
                        <textarea name="description" value={this.state.description} onChange={this.sendUserInput}  />
                    </Clipboard>
                </div>
            </div>
            <div>
                <label htmlFor="description">Preview</label>
                    <div style = {{whiteSpace: "pre-wrap"}} dangerouslySetInnerHTML={{ __html: this.state.description }}/>
            </div>
          </>
        );
      }
    }
  );

还有剪贴板组件的代码:

interface IClipboardProps {
    handlePaste: any;
}


export const Clipboard = withGlobalContext(
    class extends React.Component<IClipboardProps> {
        dropRef = React.createRef<HTMLDivElement>()
        
        constructor(props: any) {
            super(props);
           
        }

        handlePaste = (e: any) => {
            if (e.clipboardData) {
                this.props.handlePaste(e.clipboardData.items)
            }
        }

        componentDidMount() {
            const div: any = this.dropRef.current
            div.addEventListener('paste', this.handlePaste)
        }

        componentWillUnmount() {
            const div: any = this.dropRef.current
            div.removeEventListener('paste', this.handlePaste)
        }

        render() {
            return (
                <div ref={this.dropRef}>{this.props.children}</div>
            )
        }
    }
);

编辑 对于后端,我正在使用招摇。 因此,这是我在数据库(位于我的项目控制器中)中创建新项目的功能:

const Item= require("../../models/item-model.js");

function create(req, res) {
    const { title, description, author } = req.swagger.params.item.value;
    
    Item.create ({title, description, author})
    .then(itemDoc => res.status(201).json(itemDoc))
    .catch(err => {
        console.log("ERROR", err)
        res.status(404).json(err.message)});
}

这是我后端的Item模型:

const mongoose = require("mongoose");

const Schema = mongoose.Schema;


const itemSchema = new Schema({
  title: { type: String, required: true },
  description: { type: String, required: true },
  author: { type: String, required: true }
}, {
  timestamps: true
});

const Item = mongoose.model("Item", itemSchema);


module.exports = Item;

有人可以帮我吗?

0 个答案:

没有答案