在線還原數據庫備份文件

需求javascript

1.用戶上傳數據庫備份文件(.bak)還原到指定服務器上(若是用戶不上傳文件,則還原默認的備份文件)php

2.還原文件後,建立訪問該數據庫的用戶,登陸名和密碼可由用戶輸入(若是用戶不輸入登陸名和密碼,則生成默認的登陸名和密碼)css

問題html

按照需求,很容易想打使用restore database語句,代碼實現後測試發現,重複還原一個數據庫文件,會提示還原失敗,正在使用該文件。java

由於還原後在文件夾目錄中會有相同的邏輯文件名稱,因此會出現問題。jquery

解決方案web

使用restore database with move還原語句,將每次還原的文件放在不一樣的位置數據庫

代碼api

頁面代碼服務器

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>還原數據庫</title>
    <link rel="stylesheet" type="text/css" href="https://cdn.staticfile.org/webuploader/0.1.5/webuploader.css" />
    <style>
        * { padding: 0; margin: 0; }
        html, body { height: 100%; font-size: 16px; font-family: 'Microsoft YaHei'; }
        table { width: 100%; height: 100%; }
            table td { text-align: center; }
        td > input { margin: 15px 0; padding: 5px; border: 1px solid #ccc; border-radius: 3px; width: 400px; height: 30px; font-size: 16px; font-family: 'Microsoft YaHei'; }
        p { line-height: 50px; color: #999; display: none; }
        .btn { display: inline-block; text-decoration: none; color: #fff; background-color: #0094ff; padding: 10px 15px; border-radius: 3px; }
            .btn:hover { opacity: 0.9; }
        .icofile { display: none; color: green; }
        .bar { width: 100%; height: 10px; background: #999; position: relative; display: none; }
        .subbar { height: 10px; background: green; position: absolute; top: 0; left: 0; }
        .webuploader-pick { border: 1px dashed #ccc; padding: 20px 10px 20px 50px; background: url(http://www.easyicon.net/api/resizeApi.php?id=1160478&size=32) no-repeat 10px center; color: #666; }
        .tips { color: #999; line-height: 40px; }
    </style>
</head>
<body>
    <table>
        <tr>
            <td>
                <div id="uploader" style="width:400px;margin:0 auto;">
                    <div class="btns">
                        <div id="picker">選擇備份文件</div>
                        <div class="bar">
                            <div class="subbar"></div>
                        </div>
                        <div class="filelist"></div>
                    </div>
                </div>
                <div class="tips">
                    說明:不上傳備份文件,將還原默認的數據庫備份文件
                </div>
                <input type="text" placeholder="還原後數據庫名稱" id="name" /><br />
                <input type="text" placeholder="數據庫帳戶,可不填寫" id="account" /><br />
                <input type="password" placeholder="數據庫密碼,可不填寫" id="pwd" /><br />
                <a href="javascript:;" id="restore" class="btn">一鍵還原</a><br />
                <p class="tip">還原時間與文件大小成正比,請耐心等待.....</p>
            </td>
        </tr>
    </table>

    <script src="http://apps.bdimg.com/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="https://cdn.staticfile.org/webuploader/0.1.5/webuploader.js"></script>
    <script>

        $(function () {
            //文件上傳
            var uploader = WebUploader.create({
                swf: 'https://cdn.staticfile.org/webuploader/0.1.5/Uploader.swf',
                auto: true,
                server: '/Home/Upload',
                pick: {
                    id: '#picker',
                    multiple: false,
                },
                resize: false,
                fileNumLimit: 1,
                duplicate: false,//去重
                fileSizeLimit: 100 * 1024 * 1024,//100M
                accept: {
                    title: 'Bak',
                    extensions: 'bak',
                    mimeTypes: 'application/x-trash'
                }
            });
            //加入隊列前
            uploader.on('beforeFileQueued', function (file) {
                var files = uploader.getFiles();
                files.forEach(function (item) {
                    uploader.removeFile(item, true);
                });
            });
            //加入隊列時
            uploader.on('fileQueued', function (file) {
                $(".filelist").html("文件:" + file.name);
            });
            //進度條
            uploader.on('uploadProgress', function (file, percentage) {
                $(".bar").show();
                $(".subbar").css("width", percentage * 100 + "%");
            });
            //成功
            uploader.on('uploadSuccess', function (file, response) {
                $(".bar").fadeOut(2000);
                if (response.message != "OK") {
                    alert(response.message);
                }
            });
            //失敗
            uploader.on('uploadError', function (file, reason) {
                alert(reason);
            });
            //完成
            uploader.on('uploadComplete', function (file) {
            });
            //驗證
            uploader.on('error', function (msg) {
                if (msg == "Q_EXCEED_NUM_LIMIT") {
                    alert("最多選擇一個文件上傳");
                }
                else if (msg == "Q_EXCEED_SIZE_LIMIT") {
                    alert("文件最大不能超過100M");
                }
                else if (msg == "Q_TYPE_DENIED") {
                    alert("文件類型必須是BAK文件");
                }
                else if (msg == "F_DUPLICATE") {
                    alert("隊列中有同名文件了");
                }
                else {
                    alert("未知錯誤:" + msg + ",請聯繫客服");
                }
            });


            //還原數據庫文件
            $("#restore").click(function () {
                var valid = true;
                if ($("#name").val() == "") {
                    valid = false;
                    return false;
                }

                if (valid) {
                    $(this).hide();
                    $(".tip").show();

                    $.post("/Home/Restore",
                        {
                            name: $("#name").val(),
                            account: $("#account").val(),
                            pwd: $("#pwd").val(),
                            isRestoreDefault: uploader.getFiles().length == 0
                        },
                        function (data) {
                            alert(data.msg);
                            window.location.reload();
                        });
                }
            });
        });
    </script>
</body>
</html>

後臺代碼

 [HttpPost]
        public JsonResult Restore(string name, string account, string pwd, bool isRestoreDefault)
        {
            using (SqlConnection connection = new SqlConnection("Data Source=.;uid=" + Config("DBUser") + ";pwd=" + Config("DBPwd") + ";database=master;timeout=180"))
            {
                try
                {
                    connection.Open();
                    string dbNewUserName = name + "User";
                    string dbNewUserPwd = name + "User!@#";
                    if (!string.IsNullOrEmpty(account))
                    {
                        dbNewUserName = account;
                        dbNewUserPwd = pwd;
                    }

                    //備份文件獲取
                    string path = Server.MapPath("/Content/" + (isRestoreDefault ? "cms" : "temp") + ".bak");
                    List<string> logicalNameList = new List<string>();

                    //還原前,獲取數據庫備份文件的邏輯名稱
                    string cmdText = "restore filelistonly from disk='" + path + "'";
                    SqlCommand cmd = new SqlCommand(cmdText, connection);
                    cmd.CommandTimeout = Int32.MaxValue;//命令執行時間
                    SqlDataReader reader = cmd.ExecuteReader();
                    while (reader.Read())
                    {
                        logicalNameList.Add(reader["LogicalName"].ToString());
                    }
                    reader.Close();

                    //建立數據庫
                    cmdText = @"restore database " + name + " from disk='" + path + "' with";
                    string dataPath = Server.MapPath("/RestoreData/");
                    cmdText += " move '" + logicalNameList[0] + "' to '" + dataPath + name + ".mdf',";
                    cmdText += " move '" + logicalNameList[1] + "' to '" + dataPath + name + ".ldf'";
                    cmd = new SqlCommand(cmdText, connection);
                    cmd.ExecuteNonQuery();

                    //建立用戶
                    cmd = new SqlCommand("create login " + dbNewUserName + " with password='" + dbNewUserPwd + "', default_database=" + name, connection);
                    cmd.ExecuteNonQuery();

                    string dbSql = string.Format(@"use {0}
                                                            create user {1} for login {1} with default_schema=dbo
                                                            exec sp_addrolemember 'db_owner', '{1}'
                                                            ", name, dbNewUserName, dbNewUserPwd);
                    cmd = new SqlCommand(dbSql, connection);
                    cmd.ExecuteNonQuery();

                    //刪除上傳的數據庫文件
                    if (!isRestoreDefault)
                    {
                        System.IO.File.Delete(path);
                    }

                    return Json(new
                    {
                        msg = "還原成功"
                    });
                }
                catch (Exception e)
                {
                    return Json(new
                    {
                        msg = "還原失敗:" + e.Message
                    });
                }
                finally
                {
                    connection.Close();
                }
            }
        }
相關文章
相關標籤/搜索