Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

歌曲下載不完整 #149

Closed
1 task done
fuyu0425 opened this issue Jul 12, 2023 · 18 comments
Closed
1 task done

歌曲下載不完整 #149

fuyu0425 opened this issue Jul 12, 2023 · 18 comments
Labels
bug Something isn't working

Comments

@fuyu0425
Copy link
Contributor

fuyu0425 commented Jul 12, 2023

Check for existing issues

检查是否已存在相同issue

  • Completed/已检查

Describe the bug and provide steps to reproduce it

描述遇到的bug并提供相应的复现方法

調高音質或長度過長,歌曲下載不完整。

測試歌曲: 幻想楼閣 - 橋本みゆき

songLevel=higher時,檔案大概 7MB,歌曲完整 (4:48)。
songLevel=exhigh 時,檔案大概 10MB,歌曲不完整 (4:10 左右)。
我猜是 server 有 response 大小限制。
我自己有小測試一下,確實 HEAD request 能拿到 size.

可能準確不是 10M,有時大概 9M 就斷了。

問了一下ChatGPT,

in Go, how to download a big file if the server limit client body to 10m?

If you're attempting to download a large file from a server that limits client body size to 10MB, the server needs to support range requests (also known as byte serving). This will allow your Go client to request portions of the file, instead of attempting to download the entire file in a single request.

Below is an example in Go, which makes HTTP GET requests in chunks of 10MB (10 * 1024 * 1024 bytes) until the whole file is downloaded:

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strconv"
)

func main() {
	url := "http://example.com/bigfile" // Replace with your file's URL
	err := DownloadFile(url, "bigfile")
	if err != nil {
		panic(err)
	}
}

// DownloadFile will download a file from a URL and save it to the specified path.
func DownloadFile(url string, filepath string) error {
	resp, err := http.Head(url)
	if err != nil {
		return err
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("server returned %d status: %s", resp.StatusCode, http.StatusText(resp.StatusCode))
	}

	if resp.Header.Get("Accept-Ranges") != "bytes" {
		return fmt.Errorf("server does not support range requests")
	}

	size, err := strconv.Atoi(resp.Header.Get("Content-Length"))
	if err != nil {
		return err
	}

	file, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer file.Close()

	for i := 0; i < size; i += 10 * 1024 * 1024 {
		end := i + 10*1024*1024 - 1
		if end > size {
			end = size
		}

		req, err := http.NewRequest("GET", url, nil)
		if err != nil {
			return err
		}
		rangeHeader := "bytes=" + strconv.Itoa(i) + "-" + strconv.Itoa(end)
		req.Header.Add("Range", rangeHeader)

		resp, err := http.DefaultClient.Do(req)
		if err != nil {
			return err
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusPartialContent {
			// Fallback to simple download
			if _, err := io.Copy(file, resp.Body); err != nil {
				return err
			}
		}

		if _, err := io.Copy(file, resp.Body); err != nil {
			return err
		}
	}

	return nil
}

This code does the following:

  1. Makes a HEAD request to get the file size and to check if the server supports range requests.
  2. Checks the server response code and whether it accepts byte serving.
  3. Creates the file on local disk.
  4. Makes a series of GET requests to download chunks of the file, adding the Range header to each request.
  5. Writes each chunk to the file.
  6. Repeats steps 4 and 5 until the whole file is downloaded.

Please replace "http://example.com/bigfile" and "bigfile" with your actual URL and destination file path respectively.

Environment / 运行环境

go-musicfox master branch
OS: macOS 10.15.7

If applicable, list the error messages you see

如果有错误输出请一并填入

No response

If applicable, attach your ${MUSICFOX_ROOT}/musicfox.log file to this issue.

如果${MUSICFOX_ROOT}/musicfox.log里有错误日志,请一并上传

No response

@fuyu0425 fuyu0425 added the bug Something isn't working label Jul 12, 2023
@fuyu0425
Copy link
Contributor Author

順便可以再加個校對,檢查下載完的檔案的音樂時長是不是一致,不然要每個檔案檢查。

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

Windows v4.1.3 没有复现成功
1

@fuyu0425
Copy link
Contributor Author

圖片

🤔 用了 windows的機器 一樣 v4.13 還是一樣
@kylezb 你有開通會員之類的嗎?

@fuyu0425
Copy link
Contributor Author

有時會發生,有時不會。
直接 wget 倒是很穩定能下載完。

@fuyu0425
Copy link
Contributor Author

圖片 找到錯誤了
_, err = io.Copy(f, resp.Body)
if err != nil {
	errHandler(err)
	return
}

發生在 copy時

@fuyu0425
Copy link
Contributor Author

還有 歌名有 '/' 也會有錯誤,可能要 escape一下。
圖片

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

圖片 找到錯誤了   圖片 找到错误了

_, err = io.Copy(f, resp.Body)
if err != nil {
	errHandler(err)
	return
}🔄  ❓

發生在 copy時 发生在 copy 时

我这一直无法复现成功,每次下载都是正常的。这个看起来像是网络问题,感觉是超时了,你的网络环境用wget最长要多久下载完成。

@fuyu0425
Copy link
Contributor Author

圖片 人在國外 離 server (在tokyo) 比較遠 

@fuyu0425
Copy link
Contributor Author

const AppHttpTimeout = time.Second * 5

看來是超過 5秒

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

圖片 人在國外 離 server (在tokyo) 比較遠

🤔soga,那这样体验可能确实会差一些,正常情况下发生这种事情的概率比较小,我不太确定针对此类报错直接返回下载失败是不是一个好的解决方案,或者说把超时时间放进配置文件? @anhoder

@fuyu0425
Copy link
Contributor Author

畢竟每個人網速不一樣。
可以對這個獨立設置一個 timeout。
或能根據歌曲時長延長 timeout.

@anhoder
Copy link
Member

anhoder commented Jul 12, 2023

圖片 人在國外 離 server (在tokyo) 比較遠

🤔soga,那这样体验可能确实会差一些,正常情况下发生这种事情的概率比较小,我不太确定针对此类报错直接返回下载失败是不是一个好的解决方案,或者说把超时时间放进配置文件? @anhoder

下载歌曲时可以重新new个http.Client,单独设置一个比较长的超时时间,同时加上这段错误日志记录:

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

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

圖片 人在國外 離 server (在tokyo) 比較遠

🤔soga,那这样体验可能确实会差一些,正常情况下发生这种事情的概率比较小,我不太确定针对此类报错直接返回下载失败是不是一个好的解决方案,或者说把超时时间放进配置文件? @anhoder

下载歌曲时可以重新new个http.Client,单独设置一个比较长的超时时间,同时加上这段错误日志记录:

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

可以,30s应该够了吧

@anhoder
Copy link
Member

anhoder commented Jul 12, 2023

要不直接60吧

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

要不直接60吧

可以,我再看看歌名包含分隔符怎么处理比较好

@anhoder
Copy link
Member

anhoder commented Jul 12, 2023

/可以考虑直接过滤掉,或者替换为其他字符 例如:

@kylezb
Copy link
Member

kylezb commented Jul 12, 2023

/可以考虑直接过滤掉,或者替换为其他字符 例如:

我先看看能不能保留,不能再替换吧

imxyy1soope1 pushed a commit to imxyy1soope1/go-musicfox that referenced this issue Jul 14, 2023
@fuyu0425
Copy link
Contributor Author

merge #139 後,這個fix消失了 😢

kylezb added a commit to kylezb/go-musicfox that referenced this issue Jul 15, 2023
anhoder pushed a commit that referenced this issue Jun 13, 2024
anhoder pushed a commit that referenced this issue Jun 13, 2024
anhoder pushed a commit that referenced this issue Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants