session.save_path = 'C:\Windows\Temp'
solve!
2017年8月28日 星期一
Cannot start session without errors in phpMyAdmin
Cannot start session without errors, please check errors given in your PHP and/or webserver log file and configure your PHP installation properly.
2017年1月23日 星期一
C# MVC View 底下字串(string)的顯示方式
教學文章:http://demo.tc/post/679
因為需要印出html碼,所以搜尋了一下方法,發現有幾個常用的函數,以下都是我目前用過的,很少…之後有再使用到相關的東西會繼續補上
因為需要印出html碼,所以搜尋了一下方法,發現有幾個常用的函數,以下都是我目前用過的,很少…之後有再使用到相關的東西會繼續補上
- Html.Encode(string):會被編碼過後印出(在我認知就是被當成文字),像如果寫了<span>test</span>,<span>的部份不會被當成html標籤,會被當成文字直接印在頁面上。
- Html.Raw(string):不會經過編碼,如果寫了<span>test</span>,<span>會變成html的標籤,頁面上只會看到test。
@string test = "<span>test</span>"; @Html.Raw(new_head)
- HtmlString:一開始就指定此字串為html字元,作用同Html.Raw,不過要印出時只要直接@字串名稱就好。
@HtmlString test = new HtmlString("<div class=\"clearfix\"> </div></div>"); @test
2017年1月20日 星期五
C# MVC jQuery FileUpload
範例套件下載:https://github.com/daniel-williams/jQuery-File-Upload.MVC4
參考畫面(Basic Plus UI):http://blueimp.github.io/jQuery-File-Upload/
jQuery.FileUpload有分很多版本,我使用的是Basic Plus UI這一個版本。雖然NuGet套件裡也有jQuery.FileUpload,不過跟範例的版本有落差,建議大家可以先用套件的檔案,再來做調整。
至於我修改了哪些地方呢?
在根目錄下新增一個Files的資料夾,全部都佈屬好後就啟動唄!
畫面會長的像這樣,當然如果你還沒上傳過東西,列表會是空的
希望大家都能順利coding。
參考畫面(Basic Plus UI):http://blueimp.github.io/jQuery-File-Upload/
jQuery.FileUpload有分很多版本,我使用的是Basic Plus UI這一個版本。雖然NuGet套件裡也有jQuery.FileUpload,不過跟範例的版本有落差,建議大家可以先用套件的檔案,再來做調整。
至於我修改了哪些地方呢?
- 範例是抓檔案列出清單,而我的專案需要配合DB,所以改成由DB中撈出資料後再去抓上傳的圖檔。
- 原來的檔案都是上傳到同一個地方,在這邊我把它們分門別類,依照模組(modelName)的不同上傳到不同的資料夾。
- IDGen.cs
- ImageHandler.cs
- MimeTypes.cs
- ViewDataUploadFilesResult.cs
- styles/FileUpload/全部 (在專案中要改放到Content/底下)
- scripts/FileUpload/全部 (在專案中的Scripts開頭是大寫)
然後修改前4個檔案的namespace,改成自己的專案名稱,這樣等等就不需要多做using的動作了。
我們先從需要修改的檔案開始改起,首先是App_Start/RouteConfig.cs,增加綠色的部份
我們先從需要修改的檔案開始改起,首先是App_Start/RouteConfig.cs,增加綠色的部份
public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // configure HttpHandler for serving static images HttpMethodConstraint GetFileMethodConstraints = new HttpMethodConstraint(new string[] { "GET" }); Route GetFileRoute = new Route( url: "Files/{id}/{filename}", routeHandler: new DobImageRouteHandler(), defaults: null, constraints: new RouteValueDictionary { { "httpMethod", GetFileMethodConstraints } } ); routes.Add("GetFileRoute", GetFileRoute); //routes.MapRoute( // name: "Get File", // url: "Files/{id}/{filename}", // defaults: new { controller = "Files", action = "Find" }, // constraints: new { httpMethod = new HttpMethodConstraint("GET") } //); routes.MapRoute( name: "Delete File", url: "Files/{id}", defaults: new { controller = "Files", action = "Delete" }, constraints: new { httpMethod = new HttpMethodConstraint("DELETE") } ); routes.MapRoute( name: "Get Json File List", url: "Files/{id}", defaults: new { controller = "Files", action = "List" }, constraints: new { httpMethod = new HttpMethodConstraint("GET") } ); routes.MapRoute( name: "Post Files", url: "Files/{id}", defaults: new { controller = "Files", action = "Uploads" }, constraints: new { httpMethod = new HttpMethodConstraint("POST") } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Login", id = UrlParameter.Optional } ); }
再編輯BundleConfig.cs,加入綠色的部份
打開你要加入此功能的頁面,加入以下內容,因為我沒有用範例的bootstrap套件,所以css的部份有些許不同,不然按鈕上的圖示會無法顯示。原本main.js的內容則是移到頁面中,因為要加上modelName的參數
public static void RegisterBundles(BundleCollection bundles)
{
...(原本的內容)
bundles.Add(new ScriptBundle("~/bundles/jqueryfileupload").Include(
"~/Scripts/FileUpload/vendor/jquery.ui.widget.js",
"~/Scripts/FileUpload/tmpl.js",
"~/Scripts/FileUpload/load-image.js",
"~/Scripts/FileUpload/canvas-to-blob.js",
"~/Scripts/FileUpload/jquery.iframe-transport.js",
"~/Scripts/FileUpload/jquery.fileupload.js",
"~/Scripts/FileUpload/jquery.fileupload-fp.js",
"~/Scripts/FileUpload/jquery.fileupload-ui.js"));
//"~/Scripts/FileUpload/main.js"));
bundles.Add(new StyleBundle("~/Content/jqueryfileupload").Include(
"~/Content/FileUpload/jquery.fileupload-ui.css"));
}
打開你要加入此功能的頁面,加入以下內容,因為我沒有用範例的bootstrap套件,所以css的部份有些許不同,不然按鈕上的圖示會無法顯示。原本main.js的內容則是移到頁面中,因為要加上modelName的參數
<!--
加入前先檢查一下Views/Shared/_Layout.cshtml是不是有下列兩個參數了,否則會出錯
@RenderSection("scripts", required: false)
@RenderSection("styles", required: false)
//-->
@section scripts {
@Scripts.Render("~/bundles/jqueryfileupload")
}
@section styles
{
@Styles.Render("~/Content/jqueryfileupload")
}
<form id="fileupload" action="@Url.Action("Uploads","Files")" method="POST" enctype="multipart/form-data">
@Html.Hidden("modelName", "Product")
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-md-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>增加檔案...</span>
<input type="file" name="files[]" multiple>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>開始上傳</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>取消上傳</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>刪除</span>
</button>
<input type="checkbox" class="toggle">
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-md-3 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended"> </div>
</div>
<!-- go back pritave page -->
<div class="col-md-2 text-right">
<input type="button" value="返回" onclick="comeback();" class="btn btn-default" />
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
</form>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td class="preview"><span class="fade"></span></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
{% if (file.error) { %}
<td class="error" colspan="2"><span class="label label-important">Error</span> {%=file.error%}</td>
{% } else if (o.files.valid && !i) { %}
<td>
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="bar" style="width:0%;"></div></div>
</td>
<td class="start">
{% if (!o.options.autoUpload) { %}
<button class="btn btn-primary">
<i class="glyphicon glyphicon-upload"></i>
<span>開始上傳</span>
</button>
{% } %}
</td>
{% } else { %}
<td colspan="2"></td>
{% } %}
<td class="cancel">
{% if (!i) { %}
<button class="btn btn-warning">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>取消上傳</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
{% if (file.error) { %}
<td></td>
<td class="name"><span>{%=file.name%}</span></td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td class="error" colspan="2"><span class="label label-important">Error</span> {%=file.error%}</td>
{% } else { %}
<td class="preview">
<a href="{%=file.url%}" title="{%=file.name%}" data-gallery="gallery" download="{%=file.name%}"><img src="{%=file.thumbnail_url%}" class="thum" /></a>
</td>
<td class="name">
<a href="{%=file.url%}" title="{%=file.name%}" data-gallery="{%=file.thumbnail_url&&'gallery'%}" download="{%=file.name%}">{%=file.name%}</a>
</td>
<td class="size"><span>{%=o.formatFileSize(file.size)%}</span></td>
<td colspan="2"></td>
{% } %}
<td class="delete">
<button class="btn btn-danger" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}" {% if (file.delete_with_credentials) { %} data-xhr-fields='{"withCredentials":true}' {% } %}>
<i class="glyphicon glyphicon-trash"></i>
<span>刪除</span>
</button>
<input type="checkbox" name="delete" value="1">
</td>
</tr>
{% } %}
</script>
<script type="text/javascript">
function comeback() {
window.location.href = "@Url.Action("Index", "Product")";
}
$(document).ready(function () {
'use strict';
// Initialize the jQuery File Upload widget:
$('#fileupload').fileupload({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: '/Files/@Model?modelName=Product',
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 3000000,
});
// Enable iframe cross-domain access via redirect option:
$('#fileupload').fileupload(
'option',
'redirect',
window.location.href.replace(
/\/[^\/]*$/,
'/cors/result.html?%s'
)
);
// Load existing files:
$.ajax({
// Uncomment the following to send cross-domain cookies:
//xhrFields: {withCredentials: true},
url: $('#fileupload').fileupload('option', 'url'),
dataType: 'json',
context: $('#fileupload')[0]
}).done(function (result) {
$(this).fileupload('option', 'done')
.call(this, null, { result: result });
});
});
</script>
增加一個Controller檔案,命名為FilesController.cs,copy範例裡的同名檔案貼上內容,然後把所缺的東西一一 using 進來。至於db的部份,則看個人是怎麼寫的自行加上,我有寫成一個class,所以是直接引入我寫的class
protected connDB D = new connDB();
//
// GET: /Files/
private string _Dir = "D:/project";
private string _StorageRoot;
private string StorageRoot
{
get { return _StorageRoot; }
}
public FilesController()
{
//string modelName = "Product";
_StorageRoot = Path.Combine(_Dir + "/Files/");
}
[HttpGet]
public ActionResult List(int id, string modelName)
{
D.Open();
DataTable Table = D.GetTable("SELECT * FROM product_img WHERE product_id = '" + D.ToString(id) + "'");
D.Close();
var fileData = new List<ViewDataUploadFilesResult>();
DirectoryInfo dir = new DirectoryInfo(StorageRoot + modelName);
if (dir.Exists)
{
foreach (DataRow row in Table.Rows)
{
var fileNameEncoded = HttpUtility.HtmlEncode(row["filename"]);
var relativePath = "/Files/" + modelName + "/" + fileNameEncoded;
fileData.Add(new ViewDataUploadFilesResult()
{
url = relativePath,
thumbnail_url = relativePath, //@"data:image/png;base64," + EncodeFile(fullName),
name = fileNameEncoded,
type = D.ToString(row["filetype"]),
size = D.ToInt(row["filesize"]),
delete_url = "/Files/" + id + "?filename=" + fileNameEncoded + "&modelName=" + modelName,
delete_type = "DELETE"
});
}
/*
string[] extensions = MimeTypes.ImageMimeTypes.Keys.ToArray();
FileInfo[] files = dir.EnumerateFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();
if (files.Length > 0)
{
foreach (FileInfo file in files)
{
var fileId = file.Name.Substring(0, 20);
var fileNameEncoded = HttpUtility.HtmlEncode(file.Name.Substring(21));
var relativePath = "/App_Data/" + modelName + "/" + fileNameEncoded;
fileData.Add(new ViewDataUploadFilesResult()
{
url = relativePath,
thumbnail_url = relativePath, //@"data:image/png;base64," + EncodeFile(fullName),
name = fileNameEncoded,
type = MimeTypes.ImageMimeTypes[file.Extension],
size = Convert.ToInt32(file.Length),
delete_url = relativePath,
delete_type = "DELETE"
});
}
}
*/
}
var serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
var result = new ContentResult
{
Content = "{\"files\":" + serializer.Serialize(fileData) + "}",
};
return result;
}
public ActionResult Find(string id, string filename, string modelName)
{
if (id == null || filename == null)
{
return HttpNotFound();
}
//var filePath = Path.Combine(_StorageRoot, id + "-" + filename);
var filePath = Path.Combine("~/Files/" + modelName, filename);
FileStreamResult result = new FileStreamResult(new System.IO.FileStream(filePath, System.IO.FileMode.Open), GetMimeType(filePath));
result.FileDownloadName = filename;
return result;
}
[HttpPost]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Uploads(int id, string modelName)
{
var fileData = new List<ViewDataUploadFilesResult>();
D.Open();
int maxid = D.ToInt(D.GetValue("SELECT MAX(orderid) FROM product_img WHERE product_id = '" + D.ToString(id) + "'"));
maxid = (maxid < 1) ? 0 : maxid;
foreach (string file in Request.Files)
{
UploadWholeFile(modelName, id, maxid, Request, fileData);
}
D.Close();
var serializer = new JavaScriptSerializer();
serializer.MaxJsonLength = Int32.MaxValue;
var result = new ContentResult
{
Content = "{\"files\":" + serializer.Serialize(fileData) + "}",
};
return result;
}
private void UploadWholeFile(string modelName, int id, int maxid, HttpRequestBase request, List<ViewDataUploadFilesResult> statuses)
{
D.Open();
for (int i = 0; i < request.Files.Count; i++)
{
HttpPostedFileBase file = request.Files[i];
++maxid;
//upload files
string tempName = IDGen.NewID() + "_";
if (file.ContentLength == 0)
continue;
var fileName = tempName + Path.GetFileName(file.FileName);
var fileNameEncoded = HttpUtility.HtmlEncode(fileName);
var fullPath = Path.Combine(Server.MapPath("~/Files/" + modelName), fileName);
file.SaveAs(fullPath);
//save to db
Dictionary<string, string> data = new Dictionary<string, string>();
data["product_id"] = D.ToString(id);
data["filename"] = D.ToString(fileNameEncoded);
data["filesize"] = D.ToString(file.ContentLength);
data["orderid"] = D.ToString(maxid);
D.InsertDictionary("product_img", data);
statuses.Add(new ViewDataUploadFilesResult()
{
url = "/Files/" + modelName + "/" + fileNameEncoded,
thumbnail_url = "/Files/" + modelName + "/" + fileNameEncoded, //@"data:image/png;base64," + EncodeFile(fullName),
name = fileNameEncoded,
type = file.ContentType,
size = file.ContentLength,
delete_url = "/Files/" + id + "?filename=" + fileNameEncoded + "&modelName=" + modelName,
delete_type = "DELETE"
});
}
}
/*
private void UploadWholeFile(HttpRequestBase request, List<ViewDataUploadFilesResult> statuses)
{
for (int i = 0; i < request.Files.Count; i++)
{
HttpPostedFileBase file = request.Files[i];
var fileId = IDGen.NewID();
var fileName = Path.GetFileName(file.FileName);
var fileNameEncoded = HttpUtility.HtmlEncode(fileName);
var fullPath = Path.Combine(StorageRoot, fileId + "-" + fileName);
file.SaveAs(fullPath);
statuses.Add(new ViewDataUploadFilesResult()
{
url = "/Files/" + fileId + "/" + fileNameEncoded,
thumbnail_url = "/Files/" + fileId + "/" + fileNameEncoded, //@"data:image/png;base64," + EncodeFile(fullName),
name = fileNameEncoded,
type = file.ContentType,
size = file.ContentLength,
delete_url = "/Files/" + fileId + "/" + fileNameEncoded,
delete_type = "DELETE"
});
}
}
*/
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete(string id, string filename, string modelName)
{
if (id == null || filename == null || modelName == null)
{
return HttpNotFound();
}
var filePath = Path.Combine(_StorageRoot + modelName, filename);
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
D.Open();
D.DataDelete("DELETE FROM product_img WHERE filename = '" + filename + "'");
D.Close();
}
return RedirectToAction("FormImg", "Product");
}
private string EncodeFile(string fileName)
{
return Convert.ToBase64String(System.IO.File.ReadAllBytes(fileName));
}
private string GetMimeType(string filePath)
{
return GetMimeType(new FileInfo(filePath));
}
private string GetMimeType(FileInfo file)
{
return MimeTypes.ImageMimeTypes[file.Extension];
}
畫面會長的像這樣,當然如果你還沒上傳過東西,列表會是空的
希望大家都能順利coding。
訂閱:
文章 (Atom)