I am maker

prisma expressjs nodejs exceljs 파일 다운로드 기능 구현 with chat gpt (2). gpt chat에게 속았다. 본문

prisma expressjs nodejs exceljs 파일 다운로드 기능 구현 with chat gpt (2). gpt chat에게 속았다.

코딩하는고릴라 2023. 2. 13. 20:00
반응형

 

2023.02.09 - [웹] - nodejs exceljs 파일 다운로드 기능 구현 with gpt chat (1)

 

nodejs exceljs 파일 다운로드 기능 구현 with gpt chat (1)

기획쪽에서 엑셀 파일 다운로드 기능이 필요하다고 합니다. csv, xlsx 어떤 확장자가 될지 모르지만 미리 기능은 준비해둬야 하는 아주 흔한 공통 개발 상황이 닥쳐왔습니다. 엑셀 파일을 다운로

guhyeon.tistory.com

 

이전 글에 이어서

chat GPT가 알려준대로 코드에 쳐봅니다.

gpt가 말도안되는 코드를 내어놓을 수도있으니까요 ㅎㅎㅎ

 

전에 알려줬던 코드인 exceljs부분 테스트해보겠습니다.

백엔드 코드를 적어주고

const express = require('express');
const app = express();
const Excel = require('exceljs');

app.get('/download', (req, res) => {
  const workbook = new Excel.Workbook();
  const worksheet = workbook.addWorksheet('Sheet 1');
  
  worksheet.columns = [
    { header: 'Name', key: 'name' },
    { header: 'Age', key: 'age' },
    { header: 'Country', key: 'country' }
  ];
  
  worksheet.addRow({ name: 'John Doe', age: 30, country: 'United States' });
  worksheet.addRow({ name: 'Jane Doe', age: 28, country: 'Canada' });
  
  res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  res.setHeader('Content-Disposition', 'attachment; filename=data.xlsx');
  
  workbook.xlsx.write(res)
    .then(() => {
      res.end();
    });
});

app.listen(3000, () => {
  console.log('App listening on port 3000!');
});

 

화면에 버튼하나 만들어주고

<div>
   <a href={'http://localhost:3000/download'}>excelDownload</a>
</div>

누르니까 엑셀다운로드는 성공입니다!

 

이제 prisma 에서 stream으로 데이터를 다운받아오는 부분을 붙여봐야겠네요.

 

gpt 챗에서 알려준 이코드를 복붙해봤습니다.

const { prisma } = require('prisma-client');
const client = new prisma.Client();

const stream = client.query.users.stream();

stream.on('data', (user) => {
  console.log(user);
});

stream.on('end', () => {
  console.log('Streaming has ended.');
});

안되네요!

애초에 prisma-client도아니고

@prisma/client인....

 

 

 

chat gpt한테 낚였네요....

하하하.....

 

직접 구글에 찾아봤습니다.

https://github.com/prisma/prisma/issues/5055

 

Streams · Issue #5055 · prisma/prisma

Let's say I have 1.000.000 rows in my database and I need to export them to csv. As of now, Prisma Client doesn't allow you to do that easily. You need to work with a for loop and manually ...

github.com

 

아직 없는 기능이네요 하하하...

 

저 쓰레드 안에 해결방법이 보이네요.

누군가 빡고수님이 정리해놓은 코드들!

 

을 여차저차 적용해서 아래처럼 작성했는데....

 app.get('/download', async (_req, res) => {
    // create data

    const workbook = new Excel.Workbook();
    const worksheet = workbook.addWorksheet('Sheet 1');

    // // sample data
    // await context.prisma.board.createMany({
    //   data: Array.from({ length: 2000 }).map((_d, i) => {
    //     return { content: 'a' + i, title: 'a' + i, writerId: 1 };
    //   }),
    // });
    //

    // context.prisma.board.findMany({
    //   select: { title: true, content: true, createdAt: true },
    // });

    worksheet.columns = [
      { header: 'title', key: 'title' },
      { header: 'content', key: 'content' },
      { header: 'createdAt', key: 'createdAt' },
    ];

    const stream = streamReports({
      delegate: context.prisma.board,
      params: {
        select: { title: true, content: true, createdAt: true },
      },
    });
    stream.on('data', (chunk) => {
      worksheet.addRow(chunk);
    });

    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    );
    res.setHeader('Content-Disposition', 'attachment; filename=data.xlsx');

    workbook.xlsx.write(res).then(() => {
      res.end();
    });
  });

 

맙소사....

그냥 슉 빠르게 끝나버리네요...

보니까 stream으로 받아온 data를 쓰는것과 는 별개로

파일 쓰기를 그냥 끝내버려서 생기는 문제 같습니다.

 

db에서 읽어온 스트림이 끝났을 때

파일쓰기 종료를 주면 해결될 것 같네요

 

stream.on('close', () => {
      workbook.xlsx.write(res).then(() => {
        res.end();
      });
});

 

오오~ 잘 작동합니다!

 

 

단점이라면, 파일다운로드의 진행 상황이 안나오고, 진행중만 보이게되네요.

 

 

 

만약 파일 다운로드 진행상황까지 해주려고한다면

파일 생성시 파일 생성자체를 별도로 돌리고, 생성된 파일을 업로드하여

이를 다운로드 받을 수 있는 링크를 생성한다음

소켓으로 클라이언트에게 전달해줘야 할 것 같습니다.

파일이 만들어지는 과정은 progress로 소켓으로 알려주고요

 

아무튼 chat gpt!

마냥 믿을만한 녀석은 아니 었네요

 

 

 

 

최종 소스

  app.get('/download', async (_req, res) => {
    // create data

    const workbook = new Excel.Workbook();
    const worksheet = workbook.addWorksheet('Sheet 1');

    // // sample data
    // await context.prisma.board.createMany({
    //   data: Array.from({ length: 2000 }).map((_d, i) => {
    //     return { content: 'a' + i, title: 'a' + i, writerId: 1 };
    //   }),
    // });
    //

    // context.prisma.board.findMany({
    //   select: { title: true, content: true, createdAt: true },
    // });

    worksheet.columns = [
      { header: 'id', key: 'id' },
      { header: 'title', key: 'title' },
      { header: 'content', key: 'content' },
      { header: 'createdAt', key: 'createdAt' },
    ];

    const stream = streamReports({
      cursorField: 'id',
      delegate: context.prisma.board,
      params: {
        select: { id: true, title: true, content: true, createdAt: true },
      },
    });
    stream.on('data', (chunk) => {
      worksheet.addRow(chunk);
    });

    stream.on('close', () => {
      workbook.xlsx.write(res).then(() => {
        res.end();
      });
    });

    res.setHeader(
      'Content-Type',
      'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    );
    res.setHeader('Content-Disposition', 'attachment; filename=data.xlsx');
  });

 

반응형