Golang에서 S3에서 Zip을 다운로드할 때 컨텐츠를 설정하는 타임 스탬프
다음은 S3의 파일을 한데 모아 Zip 다운로드 시 내용 파일의 타임 스탬프를 계승하는 방법에 대해 설명한다.
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.Write
를 io.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
참고 자료
Reference
이 문제에 관하여(Golang에서 S3에서 Zip을 다운로드할 때 컨텐츠를 설정하는 타임 스탬프), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/RunEagler/items/40af947448b277de52eb텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)