.net mvc + layui to upload pictures (two)-use streaming to upload and download pictures

.net mvc + layui to upload pictures (two)-use streaming to upload and download pictures

Abstract: The last article wrote about a method of uploading pictures, which mentioned the limitation of that method, that is, the uploaded file can only be saved in the project directory, and the file cannot be accessed in other directories. This is related to the security mechanism of the browser. The browser does not allow users to use any path to access resources on the server, because this may cause information in other locations on the server to be leaked. The browser only allows users to use relative paths to directly access the resources under the path of this project. Then, if Project A wants to access the file resources uploaded by Project B, this will cause a problem. So this requires another way to solve this problem, that is, upload and download file resources in the form of Stream. This method does not directly access the file through the path, but first reads the file in the stream, and then writes the data in the stream to the new file, and restores the file that needs to be uploaded, so the above problem does not exist. Up. This blog post focuses on the realization of this method.

1. Preparation

First of all, do some preparatory work:

(1) Create a solution (image upload), an mvc project (Console);

(2) Then create a new controller (UploadImageController.cs);

As shown:

My demo is written on a code first implementation case, so you see that this solution has several other projects in it, but don’t worry, this case only involves the mvc project (Console), not the other projects Dependent.

(3) Introduce layui-related dependencies and write front-end code:

In this case, the front page uses layui, so the dependency of layui is introduced in advance, and then the code of the page is written (the code is copied from the layui website), as follows:

html:

<link href="~/Content/layui/css/layui.css" rel="stylesheet"/>
<script src="~/Scripts/jquery-3.3.1.min.js"></script>
<script src="~/Content/layui/layui.js"></script>
<script src="~/Content/layui/layui.all.js"></script>

<div class="layui-upload" style="margin-top:100px;">
    <button type="button" class="layui-btn" id="test1">Upload pictures</button>   
    <div class="layui-upload-list">
        <img class="layui-upload-img" id="demo1" style="width:100px;height:auto;">
        <p id="demoText"></p>
    </div>
</div>

js:

<script type="text/javascript">
layui.use('upload', function(){
  var $ = layui.jquery, upload = layui.upload;
 //Ordinary picture upload
  var uploadInst = upload.render({
       elem:'#test1',
       url:'@Url.Action("Upload", "UploadImage")'
        ,before: function(obj){
         //Pre-read local file example, ie8 is not supported
          obj.preview(function(index, file, result){
            $('#demo1').attr('src', result);//image link (base64)
          });
        }
        ,done: function(res){
           //If the upload fails
            alrt(JSON.stringify(res));
         //return layer.msg("Upload successful");
         //Uploaded successfully
        }
        ,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>

The above code is layui's image upload sample code, which can be obtained in the layui file upload section.

In the above code, just change the link at the url to the background image upload method.

as the picture shows:

Just a button, the content above and below are all included in the master page.

2. upload function realization

1. Briefly describe the process of uploading files by streaming

When using streaming to upload files, it is best to read books and have a certain understanding of related knowledge. The process of uploading files using streaming is more complicated than uploading files directly. This is actually a process of splitting a file from whole to zero, and then rebuilding it from zero to a whole after it is transferred to the corresponding location.

There are several points to understand about the use of streams:

(1) Path : path, this is the place where the file will be saved, usually Path.Conbine(path1, path2) is used. Combine the path and file name into a complete path, as follows:

 string filePath = Path.Combine(@"D:\Asp.Net\C#code\C#Basic Tutorial\Upload",fileName);

(2) Buffer array : buffer, which is a byte-type array. The data in the input stream will be stored in the buffer array in turn, and then the buffer array will write the data in the new stream (output stream);

byte[] buffer;

(3) FileStream: file stream, this class is mainly used to "read" and "write" binary data in a binary file . In the above figure, the flow of reading files and writing files is implemented by this class. Here are a few examples:

 var inputStream = new FileStream(inputfile,FileMode.Open,FileAccess.Read,FileShare.Read);

The last sentence creates a file stream object. This object has several parameters to control what kind of operation the stream performs:

inputfile: This is a file path, which means that the binary file specified by this path is read into the stream. Such as:

 var inputStream = new FileStream(@“D:\Asp.Net\C#code\C#Basic Tutorial\Upload\1.jpg”,FileMode.Open,FileAccess.Read);

Just read this 1.jpg into the stream.

FileMode: Specify the way the system opens the selected file. There are several options (enumerated values):

 //
   //Summary:
   //Specify how the operating system opens the file.
    [ComVisible(true)]
    public enum FileMode
    {
       //
       //Summary:
       //Specify that the operating system should create a new file. This requires System.Security.Permissions.FileIOPermissionAccess.Write
       //Permission. If the file already exists, System.IO.IOException will throw an exception.
        CreateNew = 1,
       //
       //Summary:
       //Specify that the operating system should create a new file. If the file already exists, it will be overwritten. This requires System.Security.Permissions.FileIOPermissionAccess.Write
       //Permission. FileMode.Create is equivalent to a request. If the file does not exist, System.IO.FileMode.CreateNew is used; otherwise, System.IO.FileMode.Truncate is used.
       //If the file already exists but is a hidden file, System.UnauthorizedAccessException will throw an exception.
        Create = 2,
       //
       //Summary:
       //Specify that the operating system should open the existing file. The ability to open the file is dependent on the value specified by the System.IO.FileAccess enumeration. A System.IO.FileNotFoundException
       //If the file does not exist, an exception will be raised.
        Open = 3,
       //
       //Summary:
       //Specify that the operating system should open a file, whether it exists, otherwise, a new file should be created. If you use FileAccess.Read to open the file, System.Security.Permissions.FileIOPermissionAccess.Read
       //Permission is required. If the file access is FileAccess.Write, System.Security.Permissions.FileIOPermissionAccess.Write
       //Permission is required. If you use FileAccess.ReadWrite, to open the file, both System.Security.Permissions.FileIOPermissionAccess.Read
       //And System.Security.Permissions.FileIOPermissionAccess.Write permissions are required.
        OpenOrCreate = 4,
       //
       //Summary:
       //Specify that the operating system should open the existing file. When opening the file, it should be truncated so that its size is zero bytes. This requires System.Security.Permissions.FileIOPermissionAccess.Write
       //Permission. Attempting to read from a file using Open FileMode.Truncate resulted in System.ArgumentException.
        Truncate = 5,
       //
       //Summary:
       //If it exists, and you find the end of the file, or create a new file, open the file. This requires System.Security.Permissions.FileIOPermissionAccess.Append
       //Permission. FileMode.Append can only be used in conjunction with FileAccess.Write. Trying to find the file will throw a System.IO.IOException before the end
       //Exception, and any attempt to read fails, a System.NotSupportedException will be thrown.
        Append = 6
    }

Several commonly used items are: FileMode.Create/CreateNew/Open/OpenOrCreate,

Among them, Open means that this stream will open this file, and Create means that a named file will be created under this path.

FileMode and FileAccess jointly control how the flow operates on files.

FileAccess: Control the permission to read or write to the file. For example, if you want to upload a file, then you must first read the data in the file, then this must be set to read, for example, the data in a file has The buffer area is read, and it needs to be stored in the specified location. At this time, the data must be written to a new file, and then write. This also has several options (enumeration values):

  //Summary:
   //Constants defined in the file for read, write or read/write access.
    [ComVisible(true)]
    [Flags]
    public enum FileAccess
    {
       //
       //Summary:
       //Read access to the file. You can read data from the file. Combine with Write for read/write access.
        Read = 1,
       //
       //Summary:
       //Write access to the file. Data can be written to this file. Combine with Read for read/write access.
        Write = 2,
       //
       //Summary:
       //Read and write access to the file. Can write and read data from files.
        ReadWrite = 3
    }

FileMode and FileAccess are used together, generally Open and Read are combined, Create and Write are combined.

(4) Offset: When the data in the stream is written (or read) into the buffer array, the data is written one by one in a similar queuing order. There is something like a pointer in the stream, and the data is read A few, the pointer will move forward a few places. The amount of the pointer moves is the offset. As an important parameter in the use of the stream, the offset plays an obvious role in the file upload in parts.

2. Realization of upload function:

Here I give the code directly, there is a detailed explanation in the code, no further explanation:

        public string Upload()
        {
           ///Get the uploaded file
            var file = Request.Files[0];
           //Get the file name of the uploaded file
            string fileName = file.FileName;
           //Upload path
            string filePath = Path.Combine(@"D:\Asp.Net\C#code\C#Basic Tutorial\Upload",fileName);
           //Define the buffer array
            byte[] buffer;
           //Stuff the file data into the stream
            var inputStream = file.InputStream;
           ///Get the length of the read data
            int readLength = Convert.ToInt32(inputStream.Length);
           ///Specify the size of the buffer array
            buffer = new byte[readLength];
           //Set the position of the pointer to the initial position
            inputStream.Seek(0,SeekOrigin.Begin);
           //Read the data of the uploaded file from position 0, and read the data into the first parameter buffer (buffer area)
            inputStream.Read(buffer,0,readLength);
           //Create an output file stream, specify the output location of the file, the mode is to create the new file, and the read and write permissions are write
            using (var outputStream = new FileStream(filePath,FileMode.Create,FileAccess.Write))
            {
               //Set the position of the pointer to the initial position
                outputStream.Seek(0,SeekOrigin.Begin);
               //Write the data in the first parameter buffer (buffer area) from the starting position to the file specified by filePath
                outputStream.Write(buffer,0,buffer.Length);
            }
        //Return the file name of the uploaded file to the front desk, indicating that the upload was successful
            return JsonConvert.SerializeObject(new {Name = fileName });
        }

After writing the file, write a link to the code at the url in the front-end js, and then run it to view the result: as shown in the figure:

Then, open the folder of the corresponding directory and check whether the file has been uploaded:

3. Another way of writing, for larger files

In the previous method, the size of the array we give is determined according to the length of the stream, because here is the uploaded image, the amount of data is not very large, there is nothing wrong with this, but if the uploaded file is relatively large, the file may not be very large. Uploaded smoothly.

Here is another upload method. Of course, it is still uploaded by streaming, but instead of defining a just-sized array and uploading it all at once, it defines a fixed-size array, taking a certain amount of data each time, and then writing the data to In the new file, empty the array again, and then use the array to fetch quantitative data, and then write it, fetch the data, and write it again, repeating like this until the file upload is complete. The following is the code of this method, there are also more detailed comments, no further explanation:

       ///<summary>
       ///File Upload
       ///</summary>
       ///<returns></returns>
        public string UploadFile()
        {
            var file = Request.Files[0];
            int BUFFERSIZE = 4096; 
            var name = string.Empty;
       //var uploadTime = DateTime.Now;
           ///The path format of the lowest directory path for file upload is/file id\file name
            var fileId = Guid.NewGuid();
            name = file.FileName;
        //var uploadPath = Path.Combine(fileId.ToString(), name);
           ///The location of the file after uploading
            var outputPath = Path.Combine(@"D:\Asp.Net\C#code\C#Basic Tutorial\Upload", name);
           ///Convert the received file into a stream
            var inputStream = file.InputStream;
           ///The offset of the stream data read into the array
            long offset = 0;
           ///Get or set the position of the cursor in the current stream
            inputStream.Position = offset;
           ///Array to store data in the stream
       //byte[] buffer = new byte[BUFFERSIZE];
           ///Read the data in the stream and read it into the array
            while (offset <inputStream.Length)
            {
               ///The array that stores the data in the stream. The size of the array is adjusted according to the amount of unread data in the stream. If the amount of unread data is greater than the specified maximum size of the array, the array size is set to the maximum capacity of the array
                byte[] buffer = new byte[Math.Min(BUFFERSIZE,inputStream.Length-offset)];
                int nRead = inputStream.Read(buffer,0,buffer.Length);
                if (nRead <0)
                {
                   ///If the reading is completed, then jump out of the loop
                    break;
                }
                try
                {
                   ///Write the data read into the array into a new file, and then save it to the specified location
                    using (var outputStream = new FileStream(outputPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        outputStream.Seek(offset, SeekOrigin.Begin);//Move the cursor in the stream after the first read data
                        outputStream.Write(buffer, 0, buffer.Length);
                        outputStream.Flush();

                        offset = outputStream.Length;
                    }
                }
                catch (Exception exception)
                {

                    throw exception;
                }

            }
            return JsonConvert.SerializeObject(new {Id = fileId,Name = name});                       
        }

Again, demonstrate whether this method can be successful:

First change the url to @Url.Action("UploadFile","UploadImage"),

,

The effect is as follows:

3. download the file

Since there are file uploads, file downloads are inevitable. Here is a file download function implementation.

1. add an a label button and an image link button to the front page, as shown in the following figure:

<div>
    <a href="@Url.Action("DownloadFile","UploadImage")">Download image</a> 
    <img src="@Url.Action("DownloadFile","UploadImage")" alt="Alternate Text" style="width:100px;height:auto;"/>
</div>

Among them, DownloadFile is the background code, and then the background code is given. Since download is the reverse process of upload, no detailed explanation is given here:

      ///<summary>
       ///File download, this case is only a file download demo, its file name and path and other information, the fixed value is directly given here, the file name and path can be flexibly given according to the actual application
       ///</summary>
       ///<returns>Return file</returns>
        public ActionResult DownloadFile()
        {
            string fileName = "Jiaolou.jpg";
            byte[] buffer;
            string contentType = "application/octec-stream";
           ///MemoryStream() memory stream
            using (var outputStream = new MemoryStream())
            {
                try
                {

                    long offset = 0;
                    string inputFilePath = Path.Combine(@"D:\Asp.Net\C#code\C#Basic Tutorial\Upload", fileName);
                    using (var inputStream = new FileStream(inputFilePath, FileMode.Open, FileAccess.Read))
                    {
                        long readLength = inputStream.Length;
                        buffer = new byte[readLength];
                        inputStream.Seek(offset,SeekOrigin.Begin);
                        inputStream.Read(buffer,0,Convert.ToInt32(readLength));
                    }
                }
                catch (Exception exception)
                {

                    throw exception;
                }
                outputStream.Write(buffer,0,buffer.Length);
                return File(outputStream.GetBuffer(),contentType,fileName);
               
            }
        }

The demo picture is given below:

Download this image:

The file is downloaded to the "download" folder on the computer by default .

The other method of uploading pictures under file.net mvc is introduced here. This article only focuses on the process of uploading and downloading files. There are many other aspects to be involved in actual applications, which will not be explained here. Allowed, I will introduce it again.

Students who need the source code of this program can leave a message mailbox, and I will send it to you as soon as possible.

I am a 5-month .net programmer and a rookie. As mentioned above, if there is a major fallacy, please criticize it!

My contact information: eMail: 3074596466@qq.com

Happy New Year everyone!

If it helps, can you give me a recommendation, hahaha! A little shameless, don't mind!

Reference: https://cloud.tencent.com/developer/article/1475584 .net mvc + layui for picture upload (two)-upload and download pictures using streaming