Răsfoiți Sursa

fix(webdav):修复WebDAV播放认证与请求头问题

- 统一使用规范的HTTP请求头字段名(如 Authorization、User-Agent)- 修复WebDAV URL编码问题,确保中文与空格正确处理
- 优化认证头设置逻辑,避免提前发起无认证的连接
- 添加Range请求头以支持流式播放
- 使用await简化异步认证头获取流程
- 移除冗余代码与重复请求头设置
- 修复潜在的认证失败未处理问题
chendeben 9 luni în urmă
părinte
comite
fedf59f60f

+ 10 - 8
entry/src/main/ets/common/util/WebdavManager.ets

@@ -774,8 +774,10 @@ export class WebdavManager {
     const host = account.isUseLocalHost ? account.localHost : account.host;
     const host = account.isUseLocalHost ? account.localHost : account.host;
     const port = account.port;
     const port = account.port;
 
 
-    // 构建基础URL,不包含认证信息
-    const filePath = `${protocol}://${host}:${port}${fileInfo.href}`;
+    // 构建基础URL,确保路径重新编码(目录/文件名中的中文与空格)
+    const encodedHref = encodeURI(fileInfo.href); // 仅编码非保留字符,已编码的百分号不重复编码
+    const filePath = `${protocol}://${host}:${port}${encodedHref}`;
+    Logger.info(TAG, '编码后的WebDAV URL: ' + filePath);
 
 
     // 创建VideoItem对象
     // 创建VideoItem对象
     // 构造函数签名: (name, id, filePath, type, videoSize, cTime, pixelMap?, size?, pixelMapPath?, artist?, album?, fileName?, lastPlayed?)
     // 构造函数签名: (name, id, filePath, type, videoSize, cTime, pixelMap?, size?, pixelMapPath?, artist?, album?, fileName?, lastPlayed?)
@@ -1109,8 +1111,8 @@ export async function buildHttpHeadersWithWebDav(
           const authHeaders = await webdavManager.getWebDavAuthHeaders(webDavAuthItem.accountId.toString());
           const authHeaders = await webdavManager.getWebDavAuthHeaders(webDavAuthItem.accountId.toString());
 
 
           if (authHeaders) {
           if (authHeaders) {
-            // 添加Basic认证头
-            headers.set("authorization", authHeaders.headers.Authorization);
+            // 添加Basic认证头(使用规范字段名)
+            headers.set("Authorization", authHeaders.headers.Authorization);
           } else {
           } else {
             Logger.error(`heanup 无法获取WebDAV认证头`);
             Logger.error(`heanup 无法获取WebDAV认证头`);
           }
           }
@@ -1122,9 +1124,10 @@ export async function buildHttpHeadersWithWebDav(
       }
       }
 
 
       // 添加标准的WebDAV请求头
       // 添加标准的WebDAV请求头
-      headers.set("user_agent", "TTMusic-WebDAV/1.0");
-      headers.set("accept", "*/*");
-      headers.set("accept-range", "bytes");
+      headers.set("User-Agent", "TTMusic-WebDAV/1.0");
+      headers.set("Accept", "*/*");
+      // 请求首段数据,触发服务器返回 206(部分内容)以适配流式播放
+      headers.set("Range", "bytes=0-");
 
 
       Logger.info(`heanup WebDAV安全认证头设置完成`);
       Logger.info(`heanup WebDAV安全认证头设置完成`);
     }
     }
@@ -1155,4 +1158,3 @@ export interface WebDavAuthItem {
   password: string;
   password: string;
   enableHttps: boolean;
   enableHttps: boolean;
 }
 }
-

+ 22 - 29
entry/src/main/ets/view/LocalMusic.ets

@@ -11716,46 +11716,39 @@ export struct LocalMusic {
 
 
     //设置视频源
     //设置视频源
     this.mIjkMediaPlayer.setDataSource(url);
     this.mIjkMediaPlayer.setDataSource(url);
-    //设置视频源http请求头
-    let headers = new Map([
-      ["user_agent", "Mozilla/5.0 BiliDroid/7.30.0 (ttmusic)"],
-      ["referer", "https://www.bilibili.com"]
-    ]);
+    // 构建规范的HTTP请求头(统一一次性设置,避免未带认证提前发起连接)
+    const headers = new Map<string, string>();
+    headers.set("User-Agent", "TTMusic-WebDAV/1.0");
+    headers.set("Accept", "*/*");
+    headers.set("Range", "bytes=0-");
     if (this.currentSong&&StrUtil.isEmpty(this.currentSong.pixelMapPath)
     if (this.currentSong&&StrUtil.isEmpty(this.currentSong.pixelMapPath)
     &&PreferencesUtil.getStringSync('COVER_API',  '') != '') {
     &&PreferencesUtil.getStringSync('COVER_API',  '') != '') {
       //如果封面为空,则搜索封面
       //如果封面为空,则搜索封面
       this.searchCover(this.currentSong,  this.currentSong.name,  this.currentSong.artist||'')
       this.searchCover(this.currentSong,  this.currentSong.name,  this.currentSong.artist||'')
     }
     }
 
 
-    // 如果是WebDAV网络音频,使用webdav_account_id获取认证信息
-    if (this.currentSong&&this.currentSong.type === CommonConstants.TYPE_WEBDAV) {
+    // 如果是WebDAV网络音频,使用webdav_account_id获取认证信息(等待完成后再设置一次性头部)
+    if (this.currentSong && this.currentSong.type === CommonConstants.TYPE_WEBDAV) {
       Logger.info(`heanup WebDAV歌曲认证 - 歌曲名: ${this.currentSong.name}, webdav_account_id: ${this.currentSong.webdav_account_id || '未设置'}`);
       Logger.info(`heanup WebDAV歌曲认证 - 歌曲名: ${this.currentSong.name}, webdav_account_id: ${this.currentSong.webdav_account_id || '未设置'}`);
-
-      // 使用webdav_account_id查询认证信息
       if (this.currentSong.webdav_account_id) {
       if (this.currentSong.webdav_account_id) {
-        const webdavManager = WebdavManager.getInstance();
-        webdavManager.buildHttpHeadersWithAccountId(this.currentSong, this.videoUrl)
-          .then(webDavHeaders => {
-            if (webDavHeaders && webDavHeaders.size > 0) {
-              // 合并WebDAV认证头到基础请求头
-              webDavHeaders.forEach((value, key) => {
-                headers.set(key, value);
-              });
-              Logger.info(`heanup 成功通过webdav_account_id获取并设置WebDAV认证头`);
-              // 重新设置带认证的请求头
-              this.mIjkMediaPlayer.setDataSourceHeader(headers);
-            } else {
-              Logger.warn(`heanup 通过webdav_account_id获取认证头失败,播放可能无法继续`);
-            }
-          })
-          .catch((error: Error) => {
-            Logger.error(`heanup 获取WebDAV认证头时出错: ${error.message}`);
-          });
+        try {
+          const webdavManager = WebdavManager.getInstance();
+          const webDavHeaders = await webdavManager.buildHttpHeadersWithAccountId(this.currentSong, this.videoUrl);
+          if (webDavHeaders && webDavHeaders.size > 0) {
+            webDavHeaders.forEach((value, key) => headers.set(key, value));
+            Logger.info(`heanup 成功通过webdav_account_id获取并合并WebDAV认证头`);
+          } else {
+            Logger.warn(`heanup 通过webdav_account_id获取认证头失败,播放可能无法继续`);
+          }
+        } catch (error) {
+          const err = error as Error;
+          Logger.error(`heanup 获取WebDAV认证头时出错: ${err.message}`);
+        }
       } else {
       } else {
         Logger.error(`heanup WebDAV歌曲 "${this.currentSong.name}" 缺少webdav_account_id,无法进行认证`);
         Logger.error(`heanup WebDAV歌曲 "${this.currentSong.name}" 缺少webdav_account_id,无法进行认证`);
-        Logger.error(`heanup 请重新扫描WebDAV账户以修复此问题`);
       }
       }
     }
     }
+    // 统一设置带认证的请求头
     this.mIjkMediaPlayer.setDataSourceHeader(headers);
     this.mIjkMediaPlayer.setDataSourceHeader(headers);
     if (this.currentSong&&this.currentSong.type === CommonConstants.TYPE_WEBDAV) {
     if (this.currentSong&&this.currentSong.type === CommonConstants.TYPE_WEBDAV) {
       console.log(`heanup 为WebDAV播放设置IjkPlayer选项`);
       console.log(`heanup 为WebDAV播放设置IjkPlayer选项`);
@@ -13695,4 +13688,4 @@ async function scanCurrentDirectoryTask(context: Context, dirPath: string, lockP
   } catch (error) {
   } catch (error) {
     console.error(' 扫描当前目录失败:', error);
     console.error(' 扫描当前目录失败:', error);
   }
   }
-}
+}