복붙노트

[MONGODB] 이미지 REST API를 항상 표시 부서에서 반환

MONGODB

이미지 REST API를 항상 표시 부서에서 반환

나는 반작용으로, 예술 포트폴리오 앱의 콘텐츠 관리 시스템을 구축하고있다. 클라이언트는 MongoDB를 삽입 할 몽구스를 사용하는 API에 게시 할 예정입니다. 이 API는 새로 삽입 된 이미지의 DB를 조회하고 클라이언트에 반환합니다.

여기에 MongoDB를가 몽구스를 사용하여 연결하는 내 코드입니다 :

mongoose.connect('mongodb://localhost/test').then(() => 
console.log('connected to db')).catch(err => console.log(err))

mongoose.Promise = global.Promise

const db = mongoose.connection

db.on('error', console.error.bind(console, 'MongoDB connection error:'))

const Schema = mongoose.Schema;

const ImgSchema = new Schema({
  img: { data: Buffer, contentType: String }
})

const Img = mongoose.model('Img', ImgSchema)

나는 이미지 파일을 처리 할 수 ​​multer 및 FS를 사용하고 있습니다. 이 같은 내 POST 엔드 포인트 외모 :

router.post('/', upload.single('image'), (req, res) => {
  if (!req.file) {
    res.send('no file')
  } else {
    const imgItem = new Img()
    imgItem.img.data = fs.readFileSync(req.file.path)
    imgItem.contentType = 'image/png'
    imgItem
      .save()
      .then(data => 
        Img.findById(data, (err, findImg) => {
          console.log(findImg.img)
          fs.writeFileSync('api/uploads/image.png', findImg.img.data)
          res.sendFile(__dirname + '/uploads/image.png')
        }))
  } 
})

나는 writeFileSync 디스크에 이미지를 기록하고있는 파일 구조를 볼 수 있습니다. res.sendFile 그것을 잡고 클라이언트로 내려 보냅니다.

클라이언트 측 코드는 다음과 같습니다 :

handleSubmit = e => {
    e.preventDefault()
    const img = new FormData()
    img.append('image', this.state.file, this.state.file.name)
    axios
      .post('http://localhost:8000/api/gallery', img, {
        onUploadProgress: progressEvent => {
          console.log(progressEvent.loaded / progressEvent.total)
        }
      })
      .then(res => {
        console.log('responsed')
        console.log(res)
        const returnedFile = new File([res.data], 'image.png', { type: 'image/png' })
        const reader = new FileReader()
        reader.onloadend = () => {
          this.setState({ returnedFile, returned: reader.result })
        }
        reader.readAsDataURL(returnedFile)
      })
      .catch(err => console.log(err))
  }

이 성공적으로 반환 된 파일 상태에있는 IMG 데이터 URL을 모두 배치 않습니다. 하지만, 내 응용 프로그램에서 이미지가 항상 깨진 표시됩니다.

다음은 몇 가지 스크린 샷입니다 :

이 문제를 어떻게 해결 하는가?

해결법

  1. ==============================

    1.다시 base64로 전송을 방지 이미지 (여러 이미지 + 큰 파일 + 큰 인코딩 된 문자열 = 아주 느린 성능을) 인코딩. 내가보기 엔 microservice을 만드는 것을 권 해드립니다 만 핸들 이미지 업로드 및 기타 이미지 관련 GET / 후 / 풋 / 삭제 요청. 기본 응용 프로그램을 분리합니다.

    다시 base64로 전송을 방지 이미지 (여러 이미지 + 큰 파일 + 큰 인코딩 된 문자열 = 아주 느린 성능을) 인코딩. 내가보기 엔 microservice을 만드는 것을 권 해드립니다 만 핸들 이미지 업로드 및 기타 이미지 관련 GET / 후 / 풋 / 삭제 요청. 기본 응용 프로그램을 분리합니다.

    예를 들면 :

    간단히 말해, 내 microservice는 이미지를 전적으로 CDN과 같은 역할을합니다.

    예를 들어, 사용자는 HTTP에 POST 요청을 보냅니다 : // localhost를 : 4000 / API / 아바타 / 일부 FormData로 만들 :

    먼저 일부 익스프레스 미들웨어를 통과 :

    libs와 / middlewares.js

    ...
    app.use(cors({credentials: true, origin: "http://localhost:3000" })) // allows receiving of cookies from front-end
    
    app.use(morgan(`tiny`)); // logging framework
    
    app.use(multer({
            limits: {
                fileSize: 10240000,
                files: 1,
                fields: 1
            },
            fileFilter: (req, file, next) => {
                if (!/\.(jpe?g|png|gif|bmp)$/i.test(file.originalname)) {
                    req.err = `That file extension is not accepted!`
                    next(null, false)
                }
                next(null, true);
            }
        }).single(`file`))
    
    app.use(bodyParser.json()); // parses header requests (req.body)
    
    app.use(bodyParser.urlencoded({ limit: `10mb`, extended: true })); // allows objects and arrays to be URL-encoded
    
    ...etc     
    

    그런 다음, 아바타 경로 안타 :

    루트 / avatars.js

    app.post(`/api/avatar/create`, requireAuth, saveImage, create);
    

    그런 다음 다음 내 saveImage 미들웨어를 통과, 일부 사용자 인증을 통과 :

    서비스 / saveImage.js

    const createRandomString = require('../shared/helpers');
    const fs = require("fs");
    const sharp = require("sharp");
    const randomString = createRandomString();
    
    if (req.err || !req.file) {
      return res.status(500).json({ err: req.err || `Unable to locate the requested file to be saved` })
      next();
    }
    
    const filename = `${Date.now()}-${randomString}-${req.file.originalname}`;
    const filepath = `uploads/${filename}`;
    
    const setFilePath = () => { req.file.path = filepath; return next();}
    
    (/\.(gif|bmp)$/i.test(req.file.originalname))
        ? fs.writeFile(filepath, req.file.buffer, (err) => {
                if (err) { 
                  return res.status(500).json({ err: `There was a problem saving the image.`}); 
                  next();
                }
    
                setFilePath();
            })
        : sharp(req.file.buffer).resize(256, 256).max().withoutEnlargement().toFile(filepath).then(() => setFilePath())
    

    파일이 저장되어있는 경우, 그 다음 내 생성 컨트롤러에 req.file.path를 보냅니다. 이합니다 (avatarFilePath 파일 경로로 및 이미지 경로로 내 DB에 저장됩니다 또는 /uploads/imagefile.ext은 제거 목적으로 저장되고 avatarURL 또는 [에 http : // localhost를 : 4000]입니다 /uploads/imagefile.ext입니다 ) 저장 및 프런트 엔드 GET 요청을 사용 :

    컨트롤러 / avatars.js은 (내가 포스트 그레스를 사용하고 있습니다,하지만 당신은 몽고에 대한 대체 할 수 있습니다)

    create: async (req, res, done) => {
                try {
                    const avatarurl = `${apiURL}/${req.file.path}`;
    
                    await db.result("INSERT INTO avatars(userid, avatarURL, avatarFilePath) VALUES ($1, $2, $3)", [req.session.id, avatarurl, req.file.path]);
    
                    res.status(201).json({ avatarurl });
                } catch (err) { return res.status(500).json({ err: err.toString() }); done(); 
            }
    

    이어서 전단 액세스 시도하는 폴더를 통해 업로드 이미지 또는 이미지, 그것은 microservice에 의해 제공됩니다 :

    libs와 / server.js

    const express = require("express");
    const path = app.get("path");
    const PORT = 4000;
    
    //============================================================//
    // EXPRESS SERVE AVATAR IMAGES
    //============================================================//
    app.use(`/uploads`, express.static(`uploads`));
    
    //============================================================//
    /* CREATE EXPRESS SERVER */
    //============================================================//
    app.listen(PORT);
    

    요청을 기록 할 때 무엇 본다 :

    19:17:54 INSERT INTO avatars(userid, avatarURL, avatarFilePath) VALUES ('08861626-b6d0-11e8-9047-672b670fe126', 'http://localhost:4000/uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png', 'uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png')
    
    POST /api/avatar/create 201 109 - 61.614 ms
    
    GET /uploads/1536891474536-k9c7OdimjEWYXbjTIs9J4S3lh2ldrzV8-android.png 200 3027 - 3.877 ms
    

    어떤 사용자 성공적인 GET 요청에 따라보고 :

  2. from https://stackoverflow.com/questions/52323381/image-returned-from-rest-api-always-displays-broken by cc-by-sa and MIT license