You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Mechanize保存文件到SMB共享驱动器时触发401认证错误

直接保存文件到SMB共享卷时Mechanize频繁抛出401 NTLM认证错误

我已连接SMB共享卷,使用Ruby的Mechanize库从专有资产管理系统批量下载文件并直接保存到共享驱动器,代码示例如下:

agent = Mechanize.new
agent.add_auth("http://website.com", username, password)
agent.get(URL).save("/Volumes/shared_folder/file.pdf")

操作最初几次可成功执行,但后续每次都会抛出401错误:

/Users/m/.rvm/rubies/ruby-2.4.6/lib/ruby/gems/2.4.0/gems/mechanize-2.7.6/lib/mechanize/http/agent.rb:775:in `response_authenticate': 401 => Net::HTTPUnauthorized for [url] -- NTLM authentication failed -- available realms:  (Mechanize::UnauthorizedError)
    from /Users/m/.rvm/rubies/ruby-2.4.6/lib/ruby/gems/2.4.0/gems/mechanize-2.7.6/lib/mechanize/http/agent.rb:323:in `fetch'
    from /Users/m/.rvm/rubies/ruby-2.4.6/lib/ruby/gems/2.4.0/gems/mechanize-2.7.6/lib/mechanize.rb:464:in `get'

如果将文件保存到脚本运行的本地工作目录,则不会出现任何错误。网站与共享驱动器的凭据不同,不确定是否与此相关。请问是否存在无需先保存到本地的解决办法?

补充说明:
添加如下rescue语句后脚本可完成执行,但每1-3次下载就会触发一次,整体方案较为繁琐:

rescue Mechanize::UnauthorizedError => e
agent = Mechanize.new
agent.add_auth("http://website.com", username, password)
retry

我还尝试设置agent.read_timeout,但无法确定每次迭代的具体耗时,因此无法设置合理值。


可行解决思路

  1. 复用Mechanize实例并重置认证
    无需每次出错都重建实例,只需重置当前实例的认证信息,减少状态初始化带来的问题:

    agent = Mechanize.new
    agent.add_auth("http://website.com", username, password)
    
    download_urls.each do |url, save_path|
      begin
        agent.get(url).save(save_path)
      rescue Mechanize::UnauthorizedError => e
        # 重置认证而非重建实例
        agent.auth("http://website.com", username, password)
        retry
      end
    end
    
  2. 禁用认证缓存
    Mechanize的NTLM认证缓存可能在跨文件系统写入时失效,强制每次请求重新验证:

    agent = Mechanize.new
    # 关闭认证缓存
    agent.http.cache_store = nil
    agent.add_auth("http://website.com", username, password)
    
  3. 分离网络请求与文件写入
    先将文件内容读取到内存,再写入SMB卷,避免IO延迟导致认证会话超时:

    agent = Mechanize.new
    agent.add_auth("http://website.com", username, password)
    
    download_urls.each do |url, save_path|
      begin
        # 先获取响应到内存
        response = agent.get(url)
        # 再写入共享卷
        File.open(save_path, 'wb') { |f| f.write(response.body) }
      rescue Mechanize::UnauthorizedError => e
        agent.auth("http://website.com", username, password)
        retry
      end
    end
    
  4. 优化SMB挂载参数
    SMB卷的写入延迟可能阻塞请求线程,导致服务器端会话超时。比如在macOS上挂载时可添加-o nobrowse或调整缓存大小,提升IO性能。

内容的提问来源于stack exchange,提问作者lumos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 04:08:11