Go에서 파일의 압축을 효율적으로 풀고 일반적인 오류를 방지하려면 어떻게 해야 합니까?

Linda Hamilton
풀어 주다: 2024-11-11 06:41:02
원래의
831명이 탐색했습니다.

How can I unzip files in Go efficiently and prevent common errors?

Go를 사용하여 손쉽게 파일 압축 해제

Go에서 파일 압축을 푸는 것은 매우 쉬울 수 있지만 때로는 장애물에 직면할 수도 있습니다. 파일의 압축을 효과적으로 풀 수 있는 간단한 솔루션을 살펴보겠습니다.

초기 코드:

다음 코드 조각을 제시했습니다.

func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer r.Close()

    for _, f := range r.File {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer rc.Close()

        path := filepath.Join(dest, f.Name)
        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            f, err := os.OpenFile(
                path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer f.Close()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
    }

    return nil
}
로그인 후 복사

최적화된 솔루션:

초기 개선 코드의 경우 다음 개선 사항을 고려하세요.

func Unzip(src, dest string) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer func() {
        if err := r.Close(); err != nil {
            panic(err)
        }
    }()

    os.MkdirAll(dest, 0755)

    // Closure to address file descriptors issue
    extractAndWriteFile := func(f *zip.File) error {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer func() {
            if err := rc.Close(); err != nil {
                panic(err)
            }
        }()

        path := filepath.Join(dest, f.Name)

        // Check for ZipSlip (Directory traversal)
        if !strings.HasPrefix(path, filepath.Clean(dest) + string(os.PathSeparator)) {
            return fmt.Errorf("illegal file path: %s", path)
        }

        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            os.MkdirAll(filepath.Dir(path), f.Mode())
            f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer func() {
                if err := f.Close(); err != nil {
                    panic(err)
                }
            }()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
        return nil
    }

    for _, f := range r.File {
        err := extractAndWriteFile(f)
        if err != nil {
            return err
        }
    }

    return nil
}
로그인 후 복사

개선 사항:

  • 대상 디렉터리 생성: 대상 디렉터리가 그렇지 않은 경우 존재합니다. 이전에 생성되었습니다. 압축 해제.
  • 파일 설명자용 클로저: 스택 연기 문제를 방지하기 위해 클로저는 파일 추출 및 쓰기 프로세스를 래핑합니다.
  • ZipSlip 방지: 검사를 통해 추출된 파일이 지정된 대상 폴더 내에 있는지 확인합니다.
  • 오류 처리: 모범 사례를 위해 Close() 작업은 오류 Patrick()으로 처리됩니다.

위 내용은 Go에서 파일의 압축을 효율적으로 풀고 일반적인 오류를 방지하려면 어떻게 해야 합니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿