.net mvc + layui to upload pictures (1)

.net mvc + layui to upload pictures (1)

  Picture uploading and display is a relatively common function in Internet applications. A recent portal project has multiple function modules that need to upload pictures. Regarding this part of the content, the original function is not complicated, but there are still some twists and turns when it is done later. Because of lack of experience, I don't know much about the methods of uploading several pictures, the scope of use, and the advantages and disadvantages, which leads to some detours when doing related functions.

  At first, I used the SaveAs(...) method to save pictures (this method is also recorded in this blog), because this method is much simpler than the other method. When I used this method to finish all the image upload modules in the background, and ready to bind the data to the front page of the portal site, a dark scene started to happen, because this method can only save the data to The folders under the current project can only be accessed by the current project. The foreground and background management systems of my portal website are two different projects. As a result, the pictures uploaded in the background cannot be obtained by the front desk of the portal website. At that time, my heart was cold, which meant that I had to redo all the modules used for uploading pictures. No experience.

  In this blog, I mainly want to record the first image upload method. The image upload control used in the front end is layui, the database is sql server, and the code first development model. In order to avoid some unnecessary additional workload, I will develop directly on one of the company’s development frameworks, but (if you are a rookie like me) don’t worry too much, because there is nothing in actual application. The company framework is tightly coupled and indispensable.

I started writing below:

1. create a table

Because the path and other information need to be saved after the image is uploaded, an Image table must be created first. The table design is as follows:

Field name

Types of

Remarks

Id

Guid

Primary key

Name

nvarchar(50)

Picture name

Url

nvarchar(50)

link

UploadTime

DateTime

Upload time

Remark

nvarchar(200)

Remarks

IsDelete

bool

Has it been deleted

Let's look at the code of the entity class and context:

1. Create a new entity class Image.cs

As shown:

code show as below:

Image.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Modules
{
    [Table("Info_Image")]
    public class Image
    {
        public Image() {
            IsDelete = false;
        }
       ///<summary>
       ///Primary key id
       ///</summary>
        public Guid Id {get; set;}

       ///<summary>
       ///Picture name
       ///</summary>
        [Required]
        [MaxLength(50)]
        public string Name {get; set;}

       ///<summary>
       ///Picture save link
       ///</summary>
        [Required]
        [MaxLength(50)]
        public string Url {get; set;}

       ///<summary>
       ///Upload time
       ///</summary>
        public DateTime UploadTime {get; set;}

       ///<summary>
       ///Remarks
       ///</summary>
        [MaxLength(200)]
        public string Remark {get; set;}

       ///<summary>
       ///delete or not
       ///</summary>
        public bool IsDelete {get; set;}
    }
}

2. Add the entity class to the context:

As shown:

Code:

MyDbContext.cs

   public DbSet<Image> Images {get; set;}

If you are in the code first development mode like me, then let the program run again, this data table should be generated in your database, haha, this is just a table building process, as long as the table can be built, any mode Okay, haha.

2. the front-end code

1. Create a new controller ImageUploadController.cs, and then create a view Index.cshtml:

Layui’s picture upload will be used here. Regarding the use of this part of the code, you can go to Layui’s official website to view : https://www.layui.com/demo/upload.html ;

The following is the page picture, and the code:

This is the page image when the background upload image code has not been written:

The following is the front-end code:

@{
    Layout = "../Shared/_TopLayout.cshtml";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width"/>
    <title>Index</title>
</head>
<body>
    <div id="picUpload">
        <div class="layui-form-item">
            <label class="layui-form-label required">Image title</label>
            <div class="layui-input-block" style="width: 554px; position: relative;">
                <input type="text" name="ImageTitle" lay-verify="required" placeholder="Image title" autocomplete="off" class="layui-input" id="ITitle">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">Remarks</label>
            <div class="layui-input-block" style="width: 554px; position: relative;">
                <textarea placeholder="Please enter content" class="layui-textarea" name="Remark"></textarea>
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-upload">
                <label class="layui-form-label">Upload pictures</label>
                <button type="button" class="layui-btn" id="test1">Upload pictures</button>
                <div class="layui-upload-list">
                    <label class="layui-form-label">Picture display</label>
                    <img class="layui-upload-img" id="demo1" style="width:200px;height:auto;">
                    <p id="demoText"></p>
                </div>
            </div>
        </div>          
   </div>
</body>
</html>
<script type="text/javascript">
    layui.use('upload', function () {
        var $ = layui.jquery;
        var upload = layui.upload;
       //Ordinary picture upload
        var uploadInst = upload.render({
            elem:'#test1',
            url:'@Url.Action("Upload","ImageUpload")',//Upload address, a controller in the background
            before: function (obj) {
                obj.preview(function (index, file, result) {
                    $('#demo1').attr('src', result);
                });
            },//The code executed before the long pass will display the image to be uploaded on the page
            done: function (res) {
                if (res.Result) {

                }
            },//Return data after the upload is successful, the background code has not been written, there is nothing to write here, and it will be added in the following content
            error: function () {
               //Demonstrate failure status and implement retransmission
                var demoText = $('#demoText');
                demoText.html('<span style="color: #FF5722;">Upload failed</span> <a class="layui-btn layui-btn-xs demo-reload">Retry</a>');
                demoText.find('.demo-reload').on('click', function () {
                    uploadInst.upload();
                });
            }
        });
    });
</script>

3. Perfect back-end code and front-end code

Next in the background link shown in the above code (

) To write the image upload code:

Post the code first, and then explain the upload ideas:

ImageUploadController.cs

///<summary>
///upload image
///</summary>
///<returns></returns>
 public ActionResult Upload()
 {
     try
     {
         HttpFileCollectionBase files = Request.Files;
         HttpPostedFileBase file = files[0];
        //Get the file name suffix
         string extName = Path.GetExtension(file.FileName).ToLower();
        //Get the physical path of the save directory
         if (System.IO.Directory.Exists(Server.MapPath("/Images/")) == false)//If it does not exist, create the images folder
         {
             System.IO.Directory.CreateDirectory(Server.MapPath("/Images/"));
         }
         string path = Server.MapPath("/Images/");//path is the absolute path of a folder, do not save directly to the database
    //string path = "F:\\TgeoSmart\\Image\\";
        //Generate the name of the new file, guid guarantees the unique image name at a certain moment (the file will not be overwritten)
         string fileNewName = Guid.NewGuid().ToString();
         string ImageUrl = path + fileNewName + extName;
        //SaveAs save the file to the specified folder
         file.SaveAs(ImageUrl);
        //This path is a relative path. Only when the relative path is saved in the database can the picture be displayed correctly (without ~ is a relative path)
         string url = "\\Images\\" + fileNewName + extName;
         return Json(new
         {
             Result = true,
             Data = url
         });
     }
     catch (Exception exception)
     {
         return Json(new
         {
             Result = false,
             exception.Message
         });
     }
 }

There are detailed comment information in the above code. What needs to be noted here is the problem of the path where we save the picture.

The Server.MapPath() function gets the absolute path of a certain folder. I posted a screenshot of Baidu about some usages of this function:

(The picture comes from a network screenshot)

From the above figure, Server.MapPath() obtains the absolute path of the picture. When actually calling the picture, considering the security of the website, the browser does not allow our page to use the absolute path to obtain the picture resource. Therefore, in the database The path saved in can only be a relative path, which is the function of this sentence in the code:

In the above code, I did not directly save the imageUrl to the database, and generated a relative path to save the image, the reason is this.

The complete front-end code is given below, including the improvement of image upload and the preservation of all information:

@{
    Layout = "../Shared/_TopLayout.cshtml";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width"/>
    <title>Index</title>
</head>
<body>
    <div id="picUpload">
<!--Add code, add information save button-->
        <div class="layui-form-item sel-fixed-right">
            <div class="layui-input-block">
                <input type="button" class="layui-btn layui-btn-small layui-btn-normal" value="Save" onclick="saveInfo()"/>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label required">Image title</label>
            <div class="layui-input-block" style="width: 554px; position: relative;">
                <input type="text" name="ImageTitle" lay-verify="required" placeholder="Image title" autocomplete="off" class="layui-input" id="iTitle">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">Remarks</label>
            <div class="layui-input-block" style="width: 554px; position: relative;">
                <textarea placeholder="Please enter content" class="layui-textarea" name="Remark" id="iRemark"></textarea>
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-upload">
                <label class="layui-form-label">Upload pictures</label>
                <button type="button" class="layui-btn" id="test1">Upload pictures</button>
                <div class="layui-upload-list">
                    <label class="layui-form-label">Show images before uploading</label>
                    <img class="layui-upload-img" id="demo1" style="width:200px;height:auto;">
                    <p id="demoText"></p>                  
                </div>
<!--Add code, the picture will be displayed after uploading-->
                <div class="layui-upload-list">
                    <label class="layui-form-label">The image will be displayed after uploading</label>
                    <img class="layui-upload-img" id="demo2" style="width:200px;height:auto;">
                </div>
            </div>
       </div>
    </div>
</body>
</html>
<script type="text/javascript">
    var imageUrl;//Add code to save the image path returned after uploading the image

    layui.use('upload', function () {
        var $ = layui.jquery;
        var upload = layui.upload;
       //Ordinary picture upload
        var uploadInst = upload.render({
            elem:'#test1',
            url:'@Url.Action("Upload","ImageUpload")',
            before: function (obj) {
                obj.preview(function (index, file, result) {
                    $('#demo1').attr('src', result);
                });
            },
            done: function (res) {
                if (res.Result) {
          //Add code to save the saved path of the returned image and bind the image to the place where the uploaded image is displayed
                    imageUrl = res.Data;
                    $("#demo2").attr("src", imageUrl);
                }
            },
            error: function () {
               //Demonstrate failure status and implement retransmission
                var demoText = $('#demoText');
                demoText.html('<span style="color: #FF5722;">Upload failed</span> <a class="layui-btn layui-btn-xs demo-reload">Retry</a>');
                demoText.find('.demo-reload').on('click', function () {
                    uploadInst.upload();
                });
            }
        });
    });

//Add code to transfer the complete information to the background to save
    var saveInfo = function () {
        $.ajax({
            type:'post',
            url:'@Url.Action("Save", "ImageUpload")',
            dataType:'json',
            data: {
                title: $("#iTitle").val(),
                remark: $("#iRemark").val(),
                url:imageUrl
            },
            success: function (res) {
                if (res.Result) {
                    alrt("Save successfully");
                }
            }
        });
    }
</script>

Then, complete the code for storing back-end information:

 public ActionResult Save(string title,string remark,string url)
 {
     try
     {
         var imageInfo = new ImageInfo() {
             Id = Guid.NewGuid(),
             Name = title,
             Url = url,
             Remark = remark,
             UploadTime = DateTime.Now.ToLocalTime()
         };
         context.ImageInfos.Add(imageInfo);
         context.SaveChanges();
         return Json(new{
             Result = true
         });

     } catch (Exception exception)
     {
         return Json(new {
             Result = true,
             exception.Message
         });
     }
 }
The following shows the page:

Then look at the information in the database:

Let's take a look at the location where our corresponding picture is saved:

have to be aware of is:

At the beginning of the article, the drawbacks of this upload method have been explained in detail, that is, this method can only save pictures in a folder under the project directory, therefore, when accessing pictures, they can only be accessed by pages in this project. To this point, this must have caused great limitations to website construction. In fact, if you want to request file resources under this project across domains, you can do so. After obtaining the image path from the database, splice the domain name of the image source project and the saved project path to form a new one. Path to access:

For example: The path I saved is this:/Images\3c2b8299-ffc3-44f9-a6d7-90a9bc02012c.jpg, the domain name of my source project is this: localhost:11163, I want to get it in the project whose domain name is localhost:10045 What should I do with this image resource?

You only need to splice the relative path and the source project domain name: localhost:11163\Images\3c2b8299-ffc3-44f9-a6d7-90a9bc02012c.jpg, it can be accessed like this.

but:

The above picture saving method is only suitable for some small Internet projects. This approach leads to tight coupling of file resources and projects. Where our project is, the file resources must be stored in the same place. Once we If the file resources are too large, the storage resources of the server will be occupied a lot, which greatly affects performance.

In the actual solution, as far as my company is concerned (I came to the company for an internship for the first time, and I don’t know how other companies get it), the file stream is used to store and read file resources. This method is used to obtain And when saving data, the data flows in binary form, so there is no browser interception of cross-domain issues. We can also choose the location of file storage as we like. In this way, we can store the file resources separately in one computer. On the server, the decoupling of file resources and project code will be realized, and the pressure on the server will be greatly reduced at the same time.

Regarding this uploading solution, when I am free, I will record it in the following blog.

If the above content is improperly expressed or purely false, please enlighten me and criticize it in the message list. I am very grateful!

Reference: https://cloud.tencent.com/developer/article/1475581 .net mvc + layui to upload pictures (1)-Cloud + Community-Tencent Cloud