博客 (62)

要在 Alibaba Cloud Linux 3 上设置开机启动 ossftp,你可以通过创建一个系统服务来实现。以下是具体步骤:

安装 ossftp:

按照阿里云官方文档安装 ossftp。

创建服务文件:

首先,你需要创建一个服务文件。使用以下命令创建一个新的服务文件:

sudo nano /etc/systemd/system/ossftp.service

编辑服务文件:

在打开的编辑器中,添加以下内容:

[Unit]
Description=OSS FTP Service
After=network.target

[Service]
ExecStart=/bin/bash /root/ossftp-1.2.0-linux-mac/start.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target

这里的 ExecStart 指向你的 start.sh 脚本的路径。

保存并退出。

重新加载系统服务:

运行以下命令以重新加载系统服务,使新创建的服务生效:

sudo systemctl daemon-reload

启用服务开机启动:

使用以下命令启用服务,使其在系统启动时自动运行:

sudo systemctl enable ossftp.service

启动服务:

你可以立即启动服务以测试其是否正常工作:

sudo systemctl start ossftp.service

检查服务状态:

使用以下命令检查服务的状态,确保它正在运行:

sudo systemctl status ossftp.service

如果一切设置正确,ossftp 应该会在每次系统启动时自动运行。


如果在你的系统上没有安装 nano 编辑器,你可以使用其他文本编辑器,比如 vi 或 vim。

如果你需要安装 nano,可以使用以下命令:

sudo yum install nano


xoyozo 1 个月前
182

宝塔面板中-安全-系统防火墙 功能非常丰富,特别是“地区规则”用来屏蔽来自国外的请求非常有用,那些通过 URL 来找网站漏洞的恶意请求大多来自国外。但是添加规则经常无反应

image.png

于是找到这个功能对应的配置文件:/etc/firewalld/zones/public.xml

<?xml version="1.0" encoding="utf-8"?>
<zone>
  <short>Public</short>
  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>
  <service name="ssh"/>
  <service name="dhcpv6-client"/>
  <port protocol="tcp" port="80"/>
  <port protocol="tcp" port="443"/>
  <masquerade/>
  <rule family="ipv4">
    <source address="43.131.232.135"/>
    <drop/>
  </rule>
  <rule family="ipv4">
    <source address="103.150.11.45"/>
    <drop/>
  </rule>
  <rule>
    <source ipset="US"/>
    <drop/>
  </rule>
  <rule>
    <source ipset="GB"/>
    <drop/>
  </rule>
</zone>

修改完成后重启防火墙。

但是看到的效果好像并不一致,甚至有时候服务器重启后防火墙是关闭的,但是有时候又是生效的。

关键的问题是CPU占用异常高。

反正宝塔的系统防火墙功能挺好挺强大,但是用起来不稳定不顺手,有些暴殄天物了。

相关阅读:

系统防火墙添加规则转圈卡死

2024年8月30日补充 :宝塔面板中配置禁用IP等规则时,提示保存成功或未提醒是否成功,但效果是未成功。其实在宝塔自己的配置里已经记录了(包含备注),但在系统防火墙配置文件中未更改成功,手动修改系统防火墙配置文件就能完全修改成功。(系统防火墙配置文件中没有备注信息,根据IP地址等规则与宝塔自己的配置文件里的记录关联后,在宝塔面板安全模块中展示出来就有备注了。)

2024年8月30日下午补充:在宝塔的软件商店找到这个应用,看到红色的说明,啥都明白了:

image.png

于是果断关闭了系统防火墙,开始研究其它替代方案。

xoyozo 4 个月前
369

本文基于 manifest v3


插件使用 Web 技术开发

浏览器提供额外的插件 API

插件与网页分离,运行在一个独立的环境中


插件 API 功能

  • 管理 Tabs、窗口、历史记录、书签、Cookies、下载、浏览数据、通知、网站权限

  • 管理浏览器的外观和感觉 - 背景、主题、右键菜单、新标签页、启动页面

  • 定制 DevTools

  • 向网页注入脚本,与网页通信,与系统中的 Native 应用程序通信

  • 修改/监听发送的 HTTP 请求/接收的回复


插件构成

结构功能调用 API操作 Dom进程
manifest配置文件-

popup弹出对话框所有
Extension process
option page用户使用的设置页面所有

background script后台脚本所有禁止?Extension process
content script内容脚本(注入到网页中)有限允许Renderer process

* 即便 content script 是注入到网页中的,而且是运行在 Renderer 进程(与主网页相同的进程),但是它们仍运行在不同的世界(world)。主网页运行在 main world,插件的 content script 运行在 isolated world。比如说 main world 中有一个变量,它在 isolated world 中是访问不到的,但是如果修改了 dom,对其它世界是有影响的。


将 Chrome 插件迁移到 Edge

  • 移除 Chrome 独有的 API(如调用 Google 账户)

  • 移动 update_URL 字段(如果是从 Chrome 商店直接下载的包会有这个字段)

  • 改名 Chrome 相关的文字(插件名称、描述文字)


参考文献

  1. Microsoft Edge 扩展入门(官方)

  2. 一小时精通Edge扩展开发Microsoft Edge 文档(视频)

xoyozo 1 年前
1,056

SignalR 是一个开源的实时通信库,用于构建实时 Web 应用程序。它提供了一个简单的 API,可以在客户端和服务器之间建立持久连接,以便实时地推送数据。

与传统的 WebSocket 相比,SignalR 提供了更高级的功能和更简单的开发体验。下面是一些主要区别:

  • 支持多种传输方式:SignalR 可以使用多种传输方式,包括 WebSocket、Server-Sent Events(SSE)、长轮询和 Forever Frame。这使得 SignalR 在不同的环境中都能提供实时通信的能力,即使某些浏览器不支持 WebSocket,也可以使用其他传输方式。

  • 自动处理连接管理:SignalR 管理连接的生命周期,包括连接的建立、断开和重新连接。它会自动处理连接的失败和重新连接的逻辑,简化了开发人员的工作。

  • 服务器端推送:SignalR 允许服务器端主动推送消息给客户端,而不需要客户端发起请求。这使得实时通信变得更加高效和实时,适用于聊天应用、实时监控等场景。

  • 跨平台支持:SignalR 可以在多个平台上使用,包括 .NET、Java、JavaScript 等。这使得开发人员可以使用自己熟悉的语言和框架来构建实时应用程序。


微软官方提供了针对 ASP.NET Core Web 应用(Razor 页面)的详细教程,这里给出 MVC 版本入门教程。


最终将创建一个正常运行的聊天应用:

signalr-get-started-finished.png


创建 Web 应用项目

image.png

image.png


添加 SignalR 客户端库

在“解决方案资源管理器”>中,右键单击项目,然后选择“添加”“客户端库”。

在“添加客户端库”对话框中:

  • “提供程序”选择“unpkg”

  • “库”,请输入 @microsoft/signalr@latest。

  • 选择“选择特定文件”,展开“dist/browser”文件夹,然后选择 signalr.js 和 signalr.min.js。

  • 点击“安装” 。

image.png


创建 SignalR Hubs 类

using Microsoft.AspNetCore.SignalR;

/// <summary>
/// Hub 类管理连接、组和消息
/// </summary>
public class ChatHub : Hub
{
        /// <summary>
        /// 可通过已连接客户端调用 SendMessage,以向所有客户端发送消息
        /// </summary>
    public async Task SendMessage(string user, string message)
    {
        // Clients.All 向所有的客户端发送消息
        // ReceiveMessage 是客户端监听的方法
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

其父类 Hub 可管理连接、组和消息。这里演示的是向所有客户端发送消息。


配置 SignalR

打开 Program.cs,添加注入:

builder.Services.AddSignalR();

添加路由:

app.MapHub<ChatHub>("/chatHub");


添加 SignalR 客户端代码

视图页面:

<div class="container">
    <div class="row p-1">
        <div class="col-1">用户</div>
        <div class="col-5"><input type="text" id="userInput" /></div>
    </div>
    <div class="row p-1">
        <div class="col-1">消息</div>
        <div class="col-5"><input type="text" class="w-100" id="messageInput" /></div>
    </div>
    <div class="row p-1">
        <div class="col-6 text-end">
            <input type="button" id="sendButton" value="发送消息" />
        </div>
    </div>
    <div class="row p-1">
        <div class="col-6">
            <hr />
        </div>
    </div>
    <div class="row p-1">
        <div class="col-6">
            <ul id="messagesList"></ul>
        </div>
    </div>
</div>
<script src="~/lib/microsoft/signalr/dist/browser/signalr.min.js"></script>
<script src="~/js/chat.js"></script>

chat.js 文件:

"use strict";

var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();

// 在连接建立之前禁用发送按钮
document.getElementById("sendButton").disabled = true;

connection.on("ReceiveMessage", function (user, message) {
    var li = document.createElement("li");
    document.getElementById("messagesList").appendChild(li);
    // 修改此处时应注意脚本注入问题
    li.textContent = `${user} says ${message}`;
});

connection.start().then(function () {
    document.getElementById("sendButton").disabled = false;
}).catch(function (err) {
    return console.error(err.toString());
});

document.getElementById("sendButton").addEventListener("click", function (event) {
    var user = document.getElementById("userInput").value;
    var message = document.getElementById("messageInput").value;
    connection.invoke("SendMessage", user, message).catch(function (err) {
        return console.error(err.toString());
    });
    event.preventDefault();
});


完成。在线示例:https://xoyozo.net/Demo/SignalRDemo






xoyozo 1 年前
1,196

推荐使用 SignalR 来平替 WebSocket,参考教程


【服务端(.NET)】

一、创建 WebSocketHandler 类,用于处理客户端发送过来的消息,并分发到其它客户端

public class WebSocketHandler
{
    private static List<WebSocket> connectedClients = [];

    public static async Task Handle(WebSocket webSocket)
    {
        connectedClients.Add(webSocket);

        byte[] buffer = new byte[1024];
        WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        while (!result.CloseStatus.HasValue)
        {
            string message = Encoding.UTF8.GetString(buffer, 0, result.Count);
            Console.WriteLine($"Received message: {message}");

            // 处理接收到的消息,例如广播给其他客户端
            await BroadcastMessage(message, webSocket);

            result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
        }

        connectedClients.Remove(webSocket);
        await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
    }

    private static async Task BroadcastMessage(string message, WebSocket sender)
    {
        foreach (var client in connectedClients)
        {
            if (client != sender && client.State == WebSocketState.Open)
            {
                await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }
    }
}

二、在 Program.cs 或 Startup.cs 中插入:

// 添加 WebSocket 路由
app.UseWebSockets();
app.Use(async (context, next) =>
{
    if (context.Request.Path == "/chat")
    {
        if (context.WebSockets.IsWebSocketRequest)
        {
            WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
            await WebSocketHandler.Handle(webSocket);
        }
        else
        {
            context.Response.StatusCode = 400;
        }
    }
    else
    {
        await next();
    }
});

这里的路由路径可以更改,此处将会创建一个 WebSocket 连接,并将其传递给 WebSocketHandler.Handle 方法进行处理。

也可以用控制器来接收 WebSocket 消息。


【客户端(JS)】

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
    <title>WebSocket 示例(JS + ASP.NET)</title>
    <style>
        #list { width: 100%; max-width: 500px; }
        .tip { color: red; }
    </style>
</head>
<body>
    <h2>WebSocket 示例(JS + ASP.NET)</h2>
    <textarea id="list" readonly rows="20"></textarea>
    <div>
        <input type="text" id="msg" />
        <button onclick="fn_send()">发送</button>
        <button onclick="fn_disconnect()">断开</button>
    </div>
    <p id="tip_required">请输入要发送的内容</p>
    <p id="tip_closed">WebSocket 连接未建立</p>

    <script>
        var wsUrl = "wss://" + window.location.hostname + ":" + window.location.port + "/chat";
        var webSocket;
        var domList = document.getElementById('list');

        // 初始化 WebSocket 并连接
        function fn_ConnectWebSocket() {
            webSocket = new WebSocket(wsUrl);

            // 向服务端发送连接请求
            webSocket.onopen = function (event) {
                var content = domList.value;
                content += "[ WebSocket 连接已建立 ]" + '\r\n';
                domList.innerHTML = content;

                document.getElementById('tip_closed').style.display = 'none';

                webSocket.send(JSON.stringify({
                    msg: 'Hello'
                }));
            };

            // 接收服务端发送的消息
            webSocket.onmessage = function (event) {
                if (event.data) {
                    var content = domList.value;
                    content += event.data + '\r\n';
                    domList.innerHTML = content;
                    domList.scrollTop = domList.scrollHeight;
                }
            };

            // 各种情况导致的连接关闭或失败
            webSocket.onclose = function (event) {
                var content = domList.value;
                content += "[ WebSocket 连接已关闭,3 秒后自动重连 ]" + '\r\n';
                domList.innerHTML = content;

                document.getElementById('tip_closed').style.display = 'block';

                setTimeout(function () {
                    var content = domList.value;
                    content += "[ 正在重连... ]" + '\r\n';
                    domList.innerHTML = content;
                    fn_ConnectWebSocket();
                }, 3000); // 3 秒后重连
            };
        }

        // 检查连接状态
        function fn_IsWebSocketConnected() {
            if (webSocket.readyState === WebSocket.OPEN) {
                document.getElementById('tip_closed').style.display = 'none';
                return true;
            } else {
                document.getElementById('tip_closed').style.display = 'block';
                return false;
            }
        }

        // 发送内容
        function fn_send() {
            if (fn_IsWebSocketConnected()) {
                var message = document.getElementById('msg').value;
                document.getElementById('tip_required').style.display = message ? 'none' : 'block';
                if (message) {
                    webSocket.send(JSON.stringify({
                        msg: message
                    }));
                }
            }
        }

        // 断开连接
        function fn_disconnect() {
            if (fn_IsWebSocketConnected()) {
                // 部分浏览器调用 close() 方法关闭 WebSocket 时不支持传参
                // webSocket.close(001, "Reason");
                webSocket.close();
            }
        }

        // 执行连接
        fn_ConnectWebSocket();
    </script>
</body>
</html>


【在线示例】

https://xoyozo.net/Demo/JsNetWebSocket


【其它】

  • 服务端以 IIS 作为 Web 服务器,那么需要安装 WebSocket 协议

  • 一个连接对应一个客户端(即 JS 中的 WebSocket 对象),注意与会话 Session 的区别

  • 在实际项目中使用应考虑兼容性问题

  • 程序设计应避免 XSS、CSRF 等安全隐患

  • 参考文档:https://learn.microsoft.com/zh-cn/aspnet/core/fundamentals/websockets

xoyozo 1 年前
794

未能找到路径“\roslyn\csc.exe”的一部分。

解决方法:

在 nuget 中直接卸载 Microsoft.CodeDom.Providers.DotNetCompilerPlatform


如果 web.config 报错,删除与 Microsoft.CodeDom.Providers.DotNetCompilerPlatform 相关的项,如:

<system.codedom>
	<compilers>
		<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701;612;618" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
		<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008,40000,40008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
	</compilers>
</system.codedom>


然后遇到错误:

功能 空传播运算符 在 C# 5 中不可用。请使用 6 或更高的语言版本


所以还是少不了 Microsoft.CodeDom.Providers.DotNetCompilerPlatform

又把这货装上了,竟然不报错了。

这期间我更改过在 Release 模式下调试,将 .NET Framework 4.8 升级到 .NET Framework 4.8.1 等,然后又退回到原来的状态和版本,竟然都正常了。

就这样吧!

xoyozo 1 年前
941

在 Vue 中,当你将一个布尔对象双向绑定到 radio 输入上时,确保 radio 的 value 属性仍然保持布尔类型是很重要的。如果 value 属性是字符串,那么 Vue 会将其解释为字符串而不是布尔值。以下是一个示例,演示如何正确地将布尔对象双向绑定到 radio 按钮,并确保 value 属性保持布尔类型:

<template>
  <div>
    <input type="radio" v-model="myBoolean" :value="true" /> True
    <input type="radio" v-model="myBoolean" :value="false" /> False
    <p>myBoolean: {{ myBoolean }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      myBoolean: false, // 布尔对象
    };
  },
};
</script>

在这个示例中,我们使用了 v-model 指令将 myBoolean 属性与两个 radio 按钮进行了双向绑定。通过将 value 属性设置为 true 和 false,我们确保了 myBoolean 属性保持布尔类型。

这样,当用户选择其中一个 radio 按钮时,myBoolean 属性将保持布尔值而不是字符串。确保 value 属性的类型与要绑定的数据类型匹配,以确保绑定的数据类型保持一致。

同样的问题出现在 select 上也是一样:

<select v-model="cat.colorId" required>
    <option :value="null">不选择</option>
    <option v-for="color in colors" :value="color.id">{{color.name}}</option>
</select>


xoyozo 1 年前
1,161

本文将详细介绍 stable diffusion webui 的下载、安装及问题解决。
Stable Diffusion 是 2022 年发布的深度学习文本到图像生成模型。它主要用于根据文本的描述产生详细图像,尽管它也可以应用于其他任务,如内补绘制、外补绘制,以及在提示词(英语)指导下产生图生图的翻译。它是一种潜在扩散模型,由慕尼黑大学的 CompVis 研究团体开发的各种生成性人工神经网络。它是由初创公司 StabilityAI,CompVis 与 Runway 合作开发的,并得到 EleutherAI 和 LAION 的支持。
其它问题请参考

一、环境准备

(一)硬件方面:

1. 显存

4G 起步,4G 显存支持生成 512*512 大小图片,超过这个大小将卡爆失败。

2. 硬盘

10G 起步,模型基本都在 5G 以上,有个 30G 硬盘不为过吧?现在硬盘容量应该不是个问题。

(二)软件方面:

1. Git

https://git-scm.com/download/win
下载最新版即可,对版本没有要求。

2. Python

https://www.python.org/downloads/
截止发稿(2023.3.6)时,最高版本只能用 3.10.*,用 3.11.* 会出问题。

3. Nvidia CUDA

https://developer.download.nvidia.cn/compute/cuda/11.7.1/local_installers/cuda_11.7.1_516.94_windows.exe
版本 11.7.1,搭配 Nvidia 驱动 516.94,可使用最新版。

4. stable-diffusion-webui

https://github.com/AUTOMATIC1111/stable-diffusion-webui
核心部件当然用最新版本~~但注意上面三个的版本的兼容性。

5. 中文语言包

https://github.com/VinsonLaro/stable-diffusion-webui-chinese
下载 chinese-all-0306.jsonchinese-english-0306.json 文件

6. 扩展(可选)

https://github.com/Mikubill/sd-webui-controlnet
下载整个 sd-webui-controlnet 压缩包

https://huggingface.co/Hetaneko/Controlnet-models/tree/main/controlnet_safetensors
https://huggingface.co/lllyasviel/ControlNet/tree/main/models
https://huggingface.co/TencentARC/T2I-Adapter/tree/main
试用时先下载第一个链接中的 control_openpose.safetensors 或 第二个链接中的 control_sd15_openpose.pth 文件

7. 模型

https://huggingface.co/models
https://civitai.com
可以网上去找推荐的一些模型,一般后缀名为 ckptptpthsafetensors ,有时也会附带 VAE(.vae.pt)或配置文件(.yaml)。

类型文件格式存放目录备注
check point.ckpt,.safetensors\models\Stable-diffusion文件较大
vae名字带有 vae 的\models\vae细节更好地恢复,特别是眼睛和文字
Textual Inversion*.pt\embeddings一般文件很小,额外的 tag
Lora*.pt\models\Lora调整模型,理解为风格化也可以
Hypernetworks.pt,.ckpt,*.safetensors\models\hypernetworks和 lora 工作方式相似,算法不同

这里可以学习一下模型的基本概念《解析不同种类的 Stable Diffusion 模型 Models,再也不用担心该用什么了

二、安装流程

1. 安装 Git

就正常安装,无问题。

2. 安装 Python

建议安装在非 program files、非 C 盘目录,以防出现目录权限问题。
注意安装时勾选 Add Python to PATH,这样可以在安装时自动加入 windows 环境变量 PATH 所需的 Python 路径。

3. 安装 Nvidia CUDA

正常安装,无问题。

4. 安装 stable-diffusion-webui

国内需要用到代理和镜像,请按照下面的步骤操作:

a) 编辑根目录下 launch.py 文件
将 https://github.com  替换为 https://ghproxy.com/https://github.com,即使用  Ghproxy 代理,加速国内 Git。
如图将代码中所有类似地址都改掉(注意:不仅仅是图中所展示的这些)。

b) 执行根目录下 webui.bat 文件
根目录下将生成 tmp 和 venv 目录。

c) 编辑 venv 目录下 pyvenv.cfg 文件
将 include-system-site-packages = false 改为 include-system-site-packages = true

d) 配置 python 库管理器 pip
方便起见,在 \venv\Scripts 下打开 cmd 后执行如下命令:

pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 镜像
pip freeze > requirements_versions.txt # 创建文件
pip install -r requirements_versions.txt # 执行此条命令前,请检查你的剩余磁盘空间
pip install xformer # 如果不执行此条命令,启动 Stable Diffusion 时可能会出现错误。xformer 还可以在后续使用中降低显卡占用。

xformer 会安装到 \venv\Lib\site-packages 中,安装失败可以用 pip install -U xformers 命试试。

e) 安装语言包
将文件 chinese-all-0306.jsonchinese-english-0306.json 放到目录 \localizations 目录中。
运行 webui 后进行配置,操作方法见下。

f) 安装扩展(可选)
将 sd-webui-controlnet 解压缩到 \extensions 目录中。
将 control_sd15_openpose.pth 文件复制到 /extensions/sd-webui-controlnet/models 目录中。
不同的扩展可能还需要安装对应的系统,比如 controlnet 要正常使用则还需要安装 ffmpeg 等。

g) 安装模型
下载的各种模型放在 \models\Stable-diffusion 目录中即可。

h) 再次执行根目录下 webui.bat 文件
用浏览器打开 webui.bat 所提供的网址即可运行。

其中提供了网址:http://127.0.0.1:7860

打开该网址后在 Settings -> User interface -> Localization (requires restart) 设置语言,在菜单中选择 chinese-all-0220(前提是已经在目录中放入了对应语言包,见上),点击 Apply Settings 确定,并且点击 Reload UI 重启界面后即可。

好了,现在可以开始使用了~~

三、问题及注意点

1. python 版本错误

错误

ERROR: Could not find a version that satisfies the requirement torch==1.13.1+cu117
ERROR: No matching distribution found for torch==1.13.1+cu117

这是由于 python 版本不对导致的(上面提过了,截止发稿时不能追求新版本),要用 python 3.10.* 版本。
解决来源:https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/7166

2. pip版本错误

警告:

[notice] A new release of pip available: 22.3.1 -> 23.0.1
[notice] To update, run: D:\stable-diffusion-webui\venv\Scripts\python.exe -m pip install --upgrade pip

提示中已经给出了解决方案:
在 \venv\Scripts\ 目录中打开 cmd,执行

python.exe -m pip install --upgrade pip

3. 安装或执行停滞

如果在执行 webui.bat 进行包下载安装时或者生成图片时会卡很久都没反应,那么这时可以复制包名,进入 python 安装目录或 \venv\Scripts\ 目录中打开 cmd,执行

pip install 包名

也可以通过任务管理查看网络状态,如果网络在玩命下载,那么就等着吧~~

4. xFormers 安装不上

很多同学都反应 xformers 无法安装,可以用以下的方法试试:

  • 检查 Dreambooth 要求的 Python 版本:
    如果您的 Python 版本低于 3.6,请安装最新的 Python 版本,并重复尝试安装 xformers。

# 据此可以在终端中运行以下命令,以检查您的 Python 版本:
python --version
  • 安装依赖项:xformers 有许多依赖项,如果这些依赖项没有正确安装可能会导致升级失败。您可以尝试安装以下依赖项:

pip install numpy scipy torch torchaudio transformers
  • 清除 pip 缓存并重新安装:

# 清除 xformers 缓存:运行以下命令清除 xformers 缓存。
pip uninstall -y xformers
pip cache purge

# 更新 pip:确保您正在使用最新版本的 pip,可以运行以下命令更新 pip。
pip install --upgrade pip

# 安装 xformers:在清除了缓存并更新了 pip 之后,重新安装 xformers。
pip install xformers
  • 手动安装 xformers 指定版本
    如果上述步骤仍然无法解决问题,可尝试手动安装 Dreambooth 所需的 xformers 版本。在 Dreambooth 的文档中,可以找到 xformers 的版本要求。

pip install xformers==0.0.17.dev465
  • 使用 conda 环境
    如果您使用的是 conda 环境,请尝试在 conda 环境中安装 xformers。

# 创建 conda 环境
conda create --name myenv

# 激活 conda 环境并安装 xformers
conda activate myenv
pip install xformers
  • 网络问题
    如果已经配置好了代理,就不要考虑这个了。
    检查网络连接:请确保您的计算机与互联网连接,并且网络连接没有被防火墙或代理服务器阻止:

# 检查网络连接是否正常
ping google.com
  • 非必要
    你确定需要使用 xformers 么?如果不需要,可以在 webui-user.bat 中把 --xformers 去掉试试。

  • 其它
    如果上述方法还是无法解决问题,请尝试在 OpenAI 的论坛或者 Dreambooth 的 GitHub 页面上寻求更多帮助。-_-!

5. 其他安装问题

删除 /tmp 和 /venv 目录后重启 webui.bat 试试。

6. 硬件问题

一般显卡不达标,就会爆卡,解决办法就是编辑根目录下 webui-user.bat 文件,试一下修改参数 COMMANDLINE_ARGS 即可。

以下几个设置逐一测试看看哪个适合自己。

set COMMANDLINE_ARGS=--lowvram --precision full --no-half --skip-torch-cuda-test
set COMMANDLINE_ARGS=--lowvram --precision full --no-half
set COMMANDLINE_ARGS=--lowvram

本机显存 4G,使用最后一个配置方法,可以烧出 2048*1080 的图,前两种方法反而会在最后爆卡。

最后,预祝各位成功~~

dog drink~~ where is dog?

在这里插入图片描述

参考:
【AI 繪畫】Stable-Diffusion 通過骨架分析插件 ControlNet 來製作超有意境的圖片
Stable Diffusion 2.1 + WebUI 的安装与使用(极详细)
低配显卡想玩 Stable Diffusion?修改一个配置就行
整合包

转自 暂时先用这个名字 2 年前
3,788

不知道从哪个版本的 Chrome 或 Edge 开始,我们无法通过 ctrl+v 快捷键将时间格式的字符串粘贴到 type 为 date 的 input 框中,我们想办法用 JS 来实现。


方式一、监听 paste 事件:

const input = document.querySelector('input[type="date"]');
input.addEventListener('paste', (event) => {
    input.value = event.clipboardData.getData('text');
});

这段代码实现了从页面获取这个 input 元素,监听它的 paste 事件,然后将粘贴板的文本内容赋值给 input。

经测试,当焦点在“年”的位置时可以粘贴成功,但焦点在“月”或“日”上不会触发 paste 事件。


方式二、监听 keydown 事件:

const input = document.querySelector('input[type="date"]');
input.addEventListener('keydown', (event) => {
    if ((navigator.platform.match("Mac") ? event.metaKey : event.ctrlKey) && event.key === 'v') {
        event.preventDefault();
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        input.value = clipboardData.getData('text');
    }
});

测试发现报错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'getData')

Uncaught TypeError: Cannot read properties of undefined (reading 'clipboardData')

看来 event 中没有 clipboardData 对象,改为从 window.navigator 获取:

const input = document.querySelector('input[type="date"]');
input.addEventListener('keydown', (event) => {
    if ((navigator.platform.match("Mac") ? event.metaKey : event.ctrlKey) && event.key === 'v') {
        event.preventDefault();
        window.navigator.clipboard.readText().then(text => {
            input.value = text;
        });
    }
});

缺点是需要用户授权:

image.png

仅第一次需要授权,如果用户拒绝,那么以后就默认拒绝了。


以上两种方式各有优缺点,选择一种适合你的方案就行。接下来继续完善。


兼容更多时间格式,并调整时区

<input type="date" /> 默认的日期格式是 yyyy-MM-dd,如果要兼容 yyyy-M-d 等格式,那么:

const parsedDate = new Date(text);
if (!isNaN(parsedDate.getTime())) {
    input.value = parsedDate.toLocaleDateString('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit' }).split('/').reverse().join('-');
}

以 text 为“2023-4-20”举例,先转为 Date,如果成功,再转为英国时间格式“20-04-2023”,以“/”分隔,逆序,再以“-”连接,就变成了“2023-04-20”。

当然如果希望支持中文的年月日,可以先用正则表达式替换一下:

text = text.replace(/\s*(\d{4})\s*年\s*(\d{1,2})\s*月\s*(\d{1,2})\s*日\s*/, "$1-$2-$3");


处理页面上的所有 <input type="date" />

const inputs = document.querySelectorAll('input[type="date"]');
inputs.forEach((input) => {
    input.addEventListener(...);
});


封装为独立域

避免全局变量污染,使用 IIFE 函数表达式:

(function() {
  // 将代码放在这里
})();

或者封装为函数,在 jQuery 的 ready 中,或 Vue 的 mounted 中调用。


在 Vue 中使用

如果将粘贴板的值直接赋值到 input.value,在 Vue 中是不能同步更新 v-model 绑定的变量的,所以需要直接赋值给变量:

<div id="app">
    <input type="date" v-model="a" data-model="a" v-on:paste="fn_pasteToDateInput" />
    {{a}}
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
    const app = Vue.createApp({
        data: function () {
            return {
                a: null,
            }
        },
        methods: {
            fn_pasteToDateInput: function (event) {
                const text = event.clipboardData.getData('text');
                const parsedDate = new Date(text);
                if (!isNaN(parsedDate.getTime())) {
                    const att = event.target.getAttribute('data-model');
                    this[att] = parsedDate.toLocaleDateString('en-GB', { year: 'numeric', month: '2-digit', day: '2-digit' }).split('/').reverse().join('-');
                }
            },
        }
    });
    const vm = app.mount('#app');
</script>

示例中 <input /> 添加了 data- 属性,值同 v-model,并使用 getAttribute() 获取,利用 this 对象的属性名赋值。 

如果你的 a 中还有嵌套对象 b,那么 data- 属性填写 a.b,方法中以“.”分割逐级查找对象并赋值

let atts = att.split('.');
let target = this;
for (let i = 0; i < atts.length - 1; i++) {
    target = target[atts[i]];
}
this.$set(target, atts[atts.length - 1], text);


xoyozo 2 年前
1,362

LigerShark.WebOptimizer.CoreBuildBundlerMinifier
特点

在运行时捆绑和缩小 CSS 和 JavaScript 文件

具有完整的服务器端和客户端缓存,以确保高性能

可禁用缩小

支持使用通配模式

标记帮助程序与缓存破坏

支持内联

支持 SCSS

将 CSS、JavaScript 或 HTML 文件捆绑到单个输出文件中

保存源文件会自动触发重新捆绑

支持通配模式

支持 CI 方案的 MSBuild 支持

缩小单个或捆绑的 CSS、JavaScript 和 HTML 文件

每种语言的缩小选项是可定制的

打开生成的文件时显示水印

任务运行程序资源管理器集成

命令行支持

快捷更新解决方案中所有捆绑包

禁止生成输出文件

转换为 Gulp

注入(Program.cs)

services.AddWebOptimizer();

app.UseWebOptimizer();


指定捆绑的项目在运行时自动缩小 css 和 js,也可以在 AddWebOptimizer 中自定义。默认情况下,生成的文件不会保存到磁盘,而是保存在缓存中。手动编辑 bundleconfig.json 文件来指定需要合并和缩小的文件
功能配置
{
  "webOptimizer": {
    // 确定是否应设置 HTTP 标头以及是否应支持条件 GET (304) 请求。在开发模式下禁用此功能可能会有所帮助。cache-control
    "enableCaching": true,
    // 确定是否用于缓存。在开发模式下禁用可能会有所帮助。IMemoryCache
    "enableMemoryCache": true,
    // 确定管道资产是否缓存到磁盘。这可以通过从磁盘加载 pipline 资产而不是重新执行管道来加快应用程序重新启动的速度。在开发模式下禁用可能会有所帮助。
    "enableDiskCache": true,
    // 设置资产将存储的目录 ifistrue。必须为读/写。enableDiskCache
    "cacheDirectory": "/var/temp/weboptimizercache",
    // 确定元素是否应指向捆绑路径或应为每个源文件创建引用。这在开发模式下禁用很有帮助。
    "enableTagHelperBundling": true,
    // 是一个绝对 URL,如果存在,它会自动为页面上的任何脚本、样式表或媒体文件添加前缀。注册标记帮助程序后,标记帮助程序会自动添加前缀。在此处查看如何注册标记帮助程序。
    "cdnUrl": "https://my-cdn.com/",
    // 确定捆绑包的源文件中没有内容时的行为,默认情况下,请求捆绑包时将引发 404 异常,设置为 true 以获取包含空内容的捆绑包。
    "allowEmptyBundle": false
  }
}


在 bundleconfig.json 捆绑时设置

[
  {
    "outputFileName": "output/bundle.css",
    "inputFiles": [
      "css/lib/**/*.css", // globbing patterns are supported
      "css/input/site.css"
    ],
    "minify": {
        "enabled": true,
        "commentMode": "all"
    }
  },
  {
    "outputFileName": "output/all.js",
    "inputFiles": [
      "js/*.js",
      "!js/ignore.js" // start with a ! to exclude files
    ]
  },
  {
    "outputFileName": "output/app.js",
    "inputFiles": [
      "input/main.js",
      "input/core/*.js" // all .js files in input/core/
    ]
  }
]


热重载(在开发模式中保存文件自动更新浏览器效果)
VS 安装扩展,方法:菜单 - 扩展 - 管理扩展 - 联机 搜索“Bundler & Minifier
其它资料
ASP.NET 官方文档


xoyozo 2 年前
2,031