Golang에서 S3에서 Zip을 다운로드할 때 컨텐츠를 설정하는 타임 스탬프

15675 단어 zipGo
개요
다음은 S3의 파일을 한데 모아 Zip 다운로드 시 내용 파일의 타임 스탬프를 계승하는 방법에 대해 설명한다.
zip화 프로세스
  • tmp 폴더에 zip 파일 설치
  • S3에서 여러 파일을 가져오는 경우
  • 가져온 파일을 Zip 파일에 기록합니다<- 이 내용의 시간 스탬프를 설정합니다
  • zip 파일을 S3에 업로드
  • tmp 폴더의 zip 파일을 삭제하고 S3의 zip 경로로 돌아갑니다
  • 목표 모듈
    archive/zip
    ※ 표준 포장
    Go 버전
    1.17.2
    zip 내의 파일 업데이트 날짜는 1979년 11월 30일입니다
    다음과 같이 zip 쓰기를 직접 실시하면 S3에 등록된 업데이트 날짜 시간에 적용되지 않아 1979년 11월 30일의 문제가 됩니다.참고 문장
    write_zip.go
    func writeZip(zipFilePath string, zipWriter *zip.Writer, srcBody []byte) error {
        writer, err := zipWriter.Create(zipFilePath)
        if err != nil {
            return err
        }
        if _, err := writer.Write(srcBody); err != nil {
            return err
        }
    
        return nil
    }
    
    writer.Writeio.Copy로 바꿨을 때도 마찬가지
    zip 내용

    해결책
    writer를 만들기 전의 헤더를 덮어쓰고 읽으면 변경 시간을 설정할 수 있습니다.
    단, zipWriter.CreateHeader에 설정된 os.FileInfo이 필요하기 때문에 os.File이 필요하기 때문에 S3에서 얻은byte 데이터를 파일을 한 번 생성한 후os를 생성한다.FileInfo를 획득하는 방법을 채택했습니다.
    지금 일시zip하는 방법.
    func writeZip(zipFilePath string, srcBody []byte, zipWriter *zip.Writer) error {
        // ユニークなtmpファイル名にする
        fw, err := os.CreateTemp("tmp/s3_zip", "zip_item_*")
        if err != nil {
            return err
        }
    
        defer os.Remove(fw.Name()) // tmp作成したファイルは忘れず消しておく
        defer fw.Close()
    
        _, err = fw.Write(srcBody)
        if err != nil {
            return err
        }
    
        fileInfo, err := fw.Stat()
        if err != nil {
            return err
        }
    
        fileHeader, _ := zip.FileInfoHeader(fileInfo)
        // Headerの場合、zipに含めるファイル名の指定が必要(sampleフォルダにsample1.jpgを配備したい場合はsample/sample1.jpgを設定する)
        fileHeader.Name = zipFilePath
        writer, err := zipWriter.CreateHeader(fileHeader)
        if err != nil {
            return err
        }
        if _, err := writer.Write(srcBody); err != nil {
            return err
        }
        return nil
    }
    
    이 경우 tmp에 S3 파일을 만드는 시간이 설정돼 있어 현재 일본시(≈zip 다운로드 시간)에는 받을 수 있다.
    zip 내용

    필요조건상 현재는 일시에 문제가 없는 상태에서 이 같은 방식으로 해결할 수 있지만 서류마다 변경된 날짜로 S3를 얻으려면 시간이 좀 더 걸린다.
    이 경우 S3 패키지의 GetObject에서 S3의 변경 날짜 시간s3.GetObjectOutput.LastModified을 받아 os.Chtimes로 설정하여 변경 날짜 시간을 변경할 수 있다.파일의 atime와 mtime를 업데이트할 수 있습니다.
    ※ atime: 방문 시간, mtime: 변경 시간
    byte 데이터 os.Chtimes 를 먼저 쓰고 호출하지 않으면 반영되지 않습니다.
    S3의 변경 날짜 및 시간으로 zip화하는 방법
    func writeZip(zipFilePath string, srcBody []byte, zipWriter *zip.Writer, srcLastModifiedAt time.Time) error {
        // ユニークなtmpファイル名にする
        fw, err := os.CreateTemp("tmp/s3_zip", "zip_item_*")
        if err != nil {
            return err
        }
        defer os.Remove(fw.Name())
        defer fw.Close()
    
        _, err = fw.Write(srcBody)
        if err != nil {
            return err
        }
    
        // --ここだけ追加--
        err = os.Chtimes(fw.Name(), srcLastModifiedAt, srcLastModifiedAt)
        if err != nil {
            return err
        }
        // ----
    
        fileInfo, err := fw.Stat()
        if err != nil {
            return err
        }
    
        fileHeader, _ := zip.FileInfoHeader(fileInfo)
        // Headerの場合、zipに含めるファイル名の指定が必要(sampleフォルダにsample1.jpgを配備したい場合はsample/sample1.jpgを設定する)
        fileHeader.Name = zipFilePath
        writer, err := zipWriter.CreateHeader(fileHeader)
        if err != nil {
            return err
        }
        if _, err := writer.Write(srcBody); err != nil {
            return err
        }
        return nil
    }
    
    // S3から中身のファイルと最終更新日時を取得する
    func (s *S3Handler) getObject(bucket string, path string) ([]byte, *time.Time, error) {
        obj, err := s.Client.GetObject(&s3.GetObjectInput{
            Bucket: aws.String(bucket),
            Key:    &path,
        })
        if err != nil {
            return []byte{}, nil, err
        }
    
        defer obj.Body.Close()
    
        buf := new(bytes.Buffer) // buffer Response Body
        buf.ReadFrom(obj.Body)
    
        return buf.Bytes(), obj.LastModified, nil
    }
    
    
    zip 내용

    총결산
    S3이 아닌 zip화된 환경에서 읽은 파일이라면 그대로 파일을 읽으면 제목에만 설정하면 예상 변경 날짜를 설정할 수 있지만, S3처럼 한 번 다운로드해 파일을 만들려면 os.Chtimes만큼 시간이 걸린다.
    참고가 되었으면 좋겠습니다.m
    참고 자료

    좋은 웹페이지 즐겨찾기