无法将图片上传到 postgres 数据库

Posted

技术标签:

【中文标题】无法将图片上传到 postgres 数据库【英文标题】:cannot upload pictures to postgres database 【发布时间】:2018-04-14 09:56:29 【问题描述】:

我在前端使用 React.js,在后端使用 Express.js API 来创建一个简单的博客。我正在为博客添加一项功能,以便能够上传图片和文件。我不断收到此错误。

 error: invalid input syntax for type bytea
at Connection.parseE (C:\Users\Sophin\desktop\testingpostg\node_modules\pg\lib\connection.js:546:11)
at Connection.parseMessage (C:\Users\Sophin\desktop\testingpostg\node_modules\pg\lib\connection.js:371:19)
at Socket.<anonymous> (C:\Users\Sophin\desktop\testingpostg\node_modules\pg\lib\connection.js:114:22)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at readableAddChunk (_stream_readable.js:176:18)
at Socket.Readable.push (_stream_readable.js:134:10)
at TCP.onread (net.js:547:20)
name: 'error',
length: 93,
severity: 'ERROR',
code: '22P02',
detail: undefined,
hint: undefined,
position: '110',
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'varlena.c',
line: '297',
routine: 'byteain' 
POST /api/learning 400 69.873 ms - 131


这是我在 React.js 中的表单

import React,  Component  from 'react';
import logo from './logo.svg';
import './App.css';
import LearningFirstComp from './components/LearningFirstComp';

class App extends Component 
 constructor(props) 
  super(props);
  this.state=
    inputTopValue:'',
    inputBottomValue:'',
    inputImageValue:,
  
  this.handleTopChange = this.handleTopChange.bind(this);
  this.handleBottomChange = this.handleBottomChange.bind(this);
  this.handleImageChange = this.handleImageChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);


handleTopChange(event) 
    this.setState(inputTopValue: event.target.value);
    console.log("changing")


handleBottomChange(event) 
    this.setState(inputBottomValue: event.target.value);
    console.log("descr")


handleImageChange(event) 
  this.setState(inputImageValue: event.target.value)
  console.log("imagechanged")


handleSubmit(event) 
    event.preventDefault();
    fetch('api/learning', 
        method: 'POST',
        headers: 'Content-Type': 'application/json',
        body: JSON.stringify(
            topstuff: event.target.topstuff.value,
            bottomstuff: event.target.bottomstuff.value,
            pic1: event.target.myimage.value
        )
    )


render() 
 return (
  <div className="App">
    <form onSubmit=this.handleSubmit encType="multipart/form-data">
      <input type="text" name="topstuff" placeholder="title" onChange=this.handleTopChange value=this.state.inputTopValue /> <br/>
      <input type="text" name="bottomstuff" placeholder="body" onChange=this.handleBottomChange value=this.state.inputBottomValue /><br/>
      <input type="file" name="myimage" onChange=this.handleImageChange value=this.state.inputImageValue /><br/>
      <input type="submit" value="Submit" />
    </form>
    <LearningFirstComp />

  </div>
  );
 


export default App;

我尝试在表单中同时使用“enctype”和“encType”,但都不起作用。


我的 postgresql 数据库的 Schema 如下所示

    CREATE TABLE IF NOT EXISTS learningtable (
     id BIGSERIAL PRIMARY KEY,
     topstuff VARCHAR(255),
     bottomstuff VARCHAR(255),
     pic1 bytea
     );

我想知道问题是否是因为错误的数据类型而发生的?我抬头发现要上传低于 1 MB 的图像,我们通常应该在 postgresql 中使用数据类型“bytea”。


这是我的 Express.js 路线
    const express = require('express');
    const myrouter = express.Router();
    const controller = require('../controllers/learningController');
    const multer = require('multer');

    var storage = multer.diskStorage(
     destination: function (req, file, cb) 
       cb(null, 'uploads')
         
       )

    var upload = multer( storage: storage );

    myrouter.post('/', upload.single('myimage'), controller.create);

    module.exports = myrouter;

我在这里使用 multer 上传文件,我认为这里一切正常?


这是我的 Express.js 控制器

    const LearningObject = require('../models/learningmodel');
    const controller = ;

    controller.create = (req, res) => 
      LearningObject.create(
        topstuff: req.body.topstuff,
        bottomstuff: req.body.bottomstuff,
        pic1: req.body.pic1,
        )
          .then(jsonAfterAdding => 
            res.json(
             message: 'okay',
             jsonAfterAdding: jsonAfterAdding
              );
          ).catch(err => 
        console.log(err);
        res.status(400).json(err);
         );
       ;

    module.exports = controller;

最后,这是我的 Express.js 模型

    const db = require('../db/config');
    const LearningObject = ;

    LearningObject.create = (randomparam) => 
      return db.one (
       `INSERT INTO learningtable
        (topstuff, bottomstuff, pic1)
          VALUES ($1, $2, $3) RETURNING *
        `,
      [randomparam.topstuff, randomparam.bottomstuff, randomparam.pic1]
      );
    ;

  module.exports = LearningObject;

任何帮助将不胜感激。

【问题讨论】:

这与你的 React 设置没有任何关系。 那会是什么? 还不确定,但它与 ReactJS 无关。我认为可以安全地排除这种可能性。您可能遇到表单提交问题,但在其他地方似乎更有可能。 修复了一个小问题,使错误消失,但仍然无法看到我文件夹中的图片。在我的handleSubmit 中,我在正文中发送了myimage,它应该是pic1,因为那是数据库表列的名称。但是还没有图片:( 请不要告诉我你是在动态使用myimage来确定数据库表列的名称。你必须小心 SQL 注入。 【参考方案1】:

第一个问题(客户端)

您正在尝试使用 javascript Fetch 方法将文件上传到服务器,同时将请求 Content-Type 设置为 application/json。请求的类型必须是 multipart/form-data

让我们为 html 表单分配一个 id 以便于参考:

<form id="myform" ...

现在我们需要获取表单元素并将其分配给一个变量:

var form = document.getElementById("myForm");

要将 fetch xhr 请求设置为 multipart/form-data Content-Type,我们需要将请求正文设置为绑定到表单元素的 FormData 对象:

body: new FormData(form)

第二个问题(服务器端)

无法访问 req.body 上上传的图片。 Multer 的专长是 multipart/form-data 请求,应用解析后的请求体与 body-parser 中间件略有不同。

我们可以通过请求file对象访问上传的图片数据。我们将通过 buffer 属性抓取图像的二进制数据。

pic1: req.file.buffer,

第三个问题(React DOM)

与浏览器 DOM 不同,React DOM 需要特殊处理。由于我们不能直接引用表单标签,所以我们需要将表单输入值存储在更改状态中。

对于文件,存储文件输入值是不够的。我们还需要存储文件object。由于我们只期望一个文件引用,我们将只获取数组中的 first 对象。

this.setState(inputImageValue: event.target.value, 
                inputImageFile: event.target.files[0])

现在在 handleSubmit 事件函数中,我们构建 FormData 对象并附加图像(附加顺序并不重要):

var formData = new FormData();
formData.append('myimage', this.state.inputImageFile);

然后我们附加输入字段的 rest

formData.append('...', this.state...);

最后我们将 formData 分配给我们的请求正文:

body: formData

【讨论】:

在客户端喜欢这样? handleSubmit(event) var myform = document.getElementById("myform"); myform.append('topstuff', event.target.topstuff.value); myform.append('bottomstuff', event.target.bottomstuff.value); myform.append('pic1', event.target.myimage.value) fetch('api/learning', method: 'POST', headers: 'Content-Type': 'multipart/form-data', 'Accept': 'application/json' , body: new FormData(myform) ) 抱歉,格式错误。我需要像上面那样附加值吗?由于某种原因它仍然不起作用:(

以上是关于无法将图片上传到 postgres 数据库的主要内容,如果未能解决你的问题,请参考以下文章

php上传图片和显示,如何实现?或者有没有插件之类的? 上传到数据库是图片文件也行,图片名也行。

图片上传存储策略

无法将图片从 Android 上传到 java 服务器

Winforms:如何使用 C# 将图片上传到 SQL Server 数据库

如何将图片从前端上传到后端

我正在将多张图片上传到 Firebase 并已完成,但我无法将 url 链接保存到列表中