Blueimp jQuery 文件上传 - 上传到不在内存中的特定文件夹

Blueimp jQuery File Upload - Upload to Specific Folder not in memory

提问人:Franco 提问时间:10/17/2023 最后编辑:Franco 更新时间:10/17/2023 访问量:31

问:

我正在使用 blueimp jquery 文件上传 (https://github.com/blueimp/jQuery-File-Upload),并按照演示和文档开发了一个用于上传文件的页面。

环境:Asp.Net Web 窗体 - .NET 4.6.1 - jquery 3.3.1

我使用了一个处理程序。 实际问题是一切似乎都很好,但是我要上传的文件不会存储在文件夹中。

似乎只在内存中起作用。 加载页面时,位于特定文件夹中的文件已收缩(为了测试,我只放置了 1 个名为 test.jpg 的文件)。 在我按下按钮上传后,处理程序中的代码已执行,但 Request.HttpMethod 始终为 GET。 没有引发错误,并且在末尾页面显示文件列表,其中包含 2 次出现相同的文件 (test.jpg)。

enter image description here

也许问题是处理程序是用 c# 编写的,调用方页面是用 vb.net 编写的?

这是内容 ASPX 页面

<%@ Page Language="vb" AutoEventWireup="false" MasterPageFile="~/Site.Master" CodeBehind="FunctionUpload.aspx.vb" Inherits="Monitor.FunctionUpload" %>


<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="FeaturedContent" runat="server">
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="MainContent" runat="server">

<link  rel="Stylesheet" type="text/css" href="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/css/jquery.fileupload.css")%>"/>
<link  rel="Stylesheet" type="text/css" href="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/css/jquery.fileupload-ui.css")%>"/>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

   
    <div class="container">
      <h1>jQuery File Upload Demo</h1>
      <blockquote class="description">
        <p>
          File Upload widget with multiple file selection, drag&amp;drop
          support, progress bars, validation and preview images, audio and video
          for jQuery.<br />
          Supports cross-domain, chunked and resumable file uploads and
          client-side image resizing.<br />
          Works with any server-side platform (PHP, Python, Ruby on Rails, Java,
          Node.js, Go etc.) that supports standard HTML form file uploads.
        </p>
      </blockquote>
      
      <div id="fileupload">
        <noscript>
            <input type="hidden"  name="redirect"
            value="https://blueimp.github.io/jQuery-File-Upload/"
        /></noscript>
        <div class="row fileupload-buttonbar">
          <div class="col-lg-7">
            <span class="btn btn-success fileinput-button">
              <i class="glyphicon glyphicon-plus"></i>
              <span>Add files...</span>
              <input type="file" name="files[]" multiple />
            </span>
            <button type="button" class="btn btn-primary start">
              <i class="glyphicon glyphicon-upload"></i>
              <span>Start upload</span>
            </button>
            <button type="reset" class="btn btn-warning cancel">
              <i class="glyphicon glyphicon-ban-circle"></i>
              <span>Cancel upload</span>
            </button>
            <button type="button" class="btn btn-danger delete">
              <i class="glyphicon glyphicon-trash"></i>
              <span>Delete selected</span>
            </button>
            <input type="checkbox" class="toggle" />
            <span class="fileupload-process"></span>
          </div>
          <div class="col-lg-5 fileupload-progress fade">
            <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>
            <div class="progress-extended">&nbsp;</div>
          </div>
        </div>

        <table role="presentation" class="table table-striped">
          <tbody class="files"></tbody>
        </table>
      </div>
      <div class="panel panel-default">
        <div class="panel-heading">
          <h3 class="panel-title">Demo Notes</h3>
        </div>
        <div class="panel-body">
          <ul>
            <li>
              The maximum file size for uploads in this demo is
              <strong>999 KB</strong> (default file size is unlimited).
            </li>
            <li>
              Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in
              this demo (by default there is no file type restriction).
            </li>
            <li>
              Uploaded files will be deleted automatically after
              <strong>5 minutes or less</strong> (demo files are stored in
              memory).
            </li>
            <li>
              You can <strong>drag &amp; drop</strong> files from your desktop
              on this webpage (see
              <a
                href="https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support"
                >Browser support</a
              >).
            </li>
            <li>
              Please refer to the
              <a href="https://github.com/blueimp/jQuery-File-Upload"
                >project website</a
              >
              and
              <a href="https://github.com/blueimp/jQuery-File-Upload/wiki"
                >documentation</a
              >
              for more information.
            </li>
            <li>
              Built with the
              <a href="https://getbootstrap.com/">Bootstrap</a> CSS framework
              and Icons from <a href="https://glyphicons.com/">Glyphicons</a>.
            </li>
          </ul>
        </div>
      </div>
    </div>

    <!-- The blueimp Gallery widget -->
    <div
      id="blueimp-gallery"
      class="blueimp-gallery blueimp-gallery-controls"
      data-filter=":even"
    >
      <div class="slides"></div>
      <h3 class="title"></h3>
      <a class="prev">‹</a>
      <a class="next">›</a>
      <a class="close">×</a>
      <a class="play-pause"></a>
      <ol class="indicator"></ol>
    </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>
                  <span class="preview"></span>
              </td>
              <td>
                  {% if (window.innerWidth > 480 || !o.options.loadImageFileTypes.test(file.type)) { %}
                      <p class="name">{%=file.name%}</p>
                  {% } %}
                  <strong class="error text-danger"></strong>
              </td>
              <td>
                  <p class="size">Processing...</p>
                  <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
              </td>
              <td>
                  {% if (!o.options.autoUpload && o.options.edit && o.options.loadImageFileTypes.test(file.type)) { %}
                    <button class="btn btn-success edit" data-index="{%=i%}" disabled>
                        <i class="glyphicon glyphicon-edit"></i>
                        <span>Edit</span>
                    </button>
                  {% } %}
                  {% if (!i && !o.options.autoUpload) { %}
                      <button class="btn btn-primary start" disabled>
                          <i class="glyphicon glyphicon-upload"></i>
                          <span>Start</span>
                      </button>
                  {% } %}
                  {% if (!i) { %}
                      <button class="btn btn-warning cancel">
                          <i class="glyphicon glyphicon-ban-circle"></i>
                          <span>Cancel</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">
              <td>
                  <span class="preview">
                      {% if (file.thumbnailUrl) { %}
                          <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
                      {% } %}
                  </span>
              </td>
              <td>
                  {% if (window.innerWidth > 480 || !file.thumbnailUrl) { %}
                      <p class="name">
                          {% if (file.url) { %}
                              <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
                          {% } else { %}
                              <span>{%=file.name%}</span>
                          {% } %}
                      </p>
                  {% } %}
                  {% if (file.error) { %}
                      <div><span class="label label-danger">Error</span> {%=file.error%}</div>
                  {% } %}
              </td>
              <td>
                  <span class="size">{%=o.formatFileSize(file.size)%}</span>
              </td>
              <td>
                  {% if (file.deleteUrl) { %}
                      <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
                          <i class="glyphicon glyphicon-trash"></i>
                          <span>Delete</span>
                      </button>
                      <input type="checkbox" name="delete" value="1" class="toggle">
                  {% } else { %}
                      <button class="btn btn-warning cancel">
                          <i class="glyphicon glyphicon-ban-circle"></i>
                          <span>Cancel</span>
                      </button>
                  {% } %}
              </td>
          </tr>
      {% } %}
    </script>
   
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/vendor/jquery.ui.widget.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/JavaScript-Templates/tmpl.min.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/JavaScript-Templates/load-image.all.min.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/JavaScript-Templates/canvas-to-blob.min.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/JavaScript-Templates/jquery.blueimp-gallery.min.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.iframe-transport.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-process.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-image.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-audio.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-video.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-validate.js")%>" type="text/javascript"></script>
    <script src="<%=Page.ResolveClientUrl("~/js/libs/jquery.fileupload/js/jquery.fileupload-ui.js")%>" type="text/javascript"></script>
    <!-- The main application script -->
    <script src="demo.js"></script>
    <!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
    <!--[if (gte IE 8)&(lt IE 10)]>
      <script src="js/cors/jquery.xdr-transport.js"></script>
    <![endif]-->

</asp:Content>

这是名为 UploadHandler_4_0.aspx 的处理程序

<%@ Page ContentType="application/json" %>

<%@ Import Namespace="System.Collections.Generic" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Runtime.Serialization" %>
<%@ Import Namespace="System.Runtime.Serialization.Json" %>

<script language="C#" runat="server">    

    private static readonly FilesDisposition FILES_DISPOSITION = FilesDisposition.ServerRoot;
    //private static readonly string FILES_PATH = @"/files";
    private static readonly string FILES_PATH = "~/Function/server/upload";    
    
    private static readonly string FILE_QUERY_VAR = "file";
    private static readonly string FILE_GET_CONTENT_TYPE = "application/octet-stream";
    
    private static readonly int ATTEMPTS_TO_WRITE = 3;
    private static readonly int ATTEMPT_WAIT = 100; //msec

    private static readonly int BUFFER_SIZE = 4 * 1024 * 1024;
    
    private enum FilesDisposition
    {
        ServerRoot,
        HandlerRoot,
        Absolute
    }
        
    private static class HttpMethods
    {
        public static readonly string GET = "GET";
        public static readonly string POST = "POST";
        public static readonly string DELETE = "DELETE";
    }

    [DataContract]
    private class FileResponse
    {
        [DataMember]
        public string name;
        [DataMember]
        public long size;
        [DataMember]
        public string type;
        [DataMember]
        public string url;
        [DataMember]
        public string error;
        [DataMember]
        public string deleteUrl;
        [DataMember]
        public string deleteType;
    }
    
    [DataContract]
    private class UploaderResponse
    {
        [DataMember]
        public FileResponse[] files;

        public UploaderResponse(FileResponse[] fileResponses)
        {
            files = fileResponses;
        }
    }
    
    private string CreateFileUrl(string fileName, FilesDisposition filesDisposition)
    {
        switch (filesDisposition)
        {
            case FilesDisposition.ServerRoot:
                // 1. files directory lies in root directory catalog WRONG
                return String.Format("{0}{1}/{2}", Request.Url.GetLeftPart(UriPartial.Authority),
                    FILES_PATH, Path.GetFileName(fileName));

            case FilesDisposition.HandlerRoot:
                // 2. files directory lays in current page catalog WRONG
                return String.Format("{0}{1}{2}/{3}", Request.Url.GetLeftPart(UriPartial.Authority), 
                    Path.GetDirectoryName(Request.CurrentExecutionFilePath).Replace(@"\", @"/"), FILES_PATH, Path.GetFileName(fileName));

            case FilesDisposition.Absolute:
                // 3. files directory lays anywhere YEAH
                return String.Format("{0}?{1}={2}", Request.Url.AbsoluteUri, FILE_QUERY_VAR, HttpUtility.UrlEncode(Path.GetFileName(fileName)));
            default:
                return String.Empty;
        }
    }
    
    private FileResponse CreateFileResponse(string fileName, long size, string error)
    {
        return new FileResponse()
        {
            name = Path.GetFileName(fileName),
            size = size,
            type = String.Empty,
            url = CreateFileUrl(fileName, FILES_DISPOSITION),
            error = error,
            deleteUrl = CreateFileUrl(fileName, FilesDisposition.Absolute),
            deleteType = HttpMethods.DELETE
        };
    }

    private void SerializeUploaderResponse(List<FileResponse> fileResponses)
    {
        DataContractJsonSerializer Serializer = new DataContractJsonSerializer(typeof(UploaderResponse));
        
        Serializer.WriteObject(Response.OutputStream, new UploaderResponse(fileResponses.ToArray()));        
    }
    
    private void FromStreamToStream(Stream source, Stream destination)
    {
        int BufferSize = source.Length >= BUFFER_SIZE ? BUFFER_SIZE : (int)source.Length;
        long BytesLeft = source.Length;

        byte[] Buffer = new byte[BufferSize];

        int BytesRead = 0;

        while (BytesLeft > 0)
        {
            BytesRead = source.Read(Buffer, 0, BytesLeft > BufferSize ? BufferSize : (int)BytesLeft);

            destination.Write(Buffer, 0, BytesRead);

            BytesLeft -= BytesRead;
        }
    }
    
    protected void Page_Load(object sender, EventArgs e)
    {
        string FilesPath;

        switch (FILES_DISPOSITION)
        {
            case FilesDisposition.ServerRoot:
                FilesPath = Server.MapPath(FILES_PATH);
                break;
            case FilesDisposition.HandlerRoot:
                FilesPath = Server.MapPath(Path.GetDirectoryName(Request.CurrentExecutionFilePath) + FILES_PATH);
                break;
            case FilesDisposition.Absolute:
                FilesPath = FILES_PATH;
                break;
            default:
                Response.StatusCode = 500;
                Response.StatusDescription = "Configuration error (FILES_DISPOSITION)";
                return;
        }   

        // prepare directory
        if (!Directory.Exists(FilesPath))
        {
            Directory.CreateDirectory(FilesPath);
        }


        string QueryFileName = Request[FILE_QUERY_VAR];
        string FullFileName = null;
        string ShortFileName = null;

        //if (!String.IsNullOrEmpty(QueryFileName))
        if (QueryFileName != null) // param specified, but maybe in wrong format (empty). else user will download json with listed files
        {
            ShortFileName = HttpUtility.UrlDecode(QueryFileName);
            FullFileName = String.Format(@"{0}\{1}", FilesPath, ShortFileName);

            if (QueryFileName.Trim().Length == 0 || !File.Exists(FullFileName))
            {
                Response.StatusCode = 404;
                Response.StatusDescription = "File not found";

                Response.End();
                return;
            }
        }       
        
        if (Request.HttpMethod.ToUpper() == HttpMethods.GET)
        {           
            if (FullFileName != null)
            {
                Response.ContentType = FILE_GET_CONTENT_TYPE; 
                Response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}{1}", Path.GetFileNameWithoutExtension(ShortFileName), Path.GetExtension(ShortFileName).ToUpper()));

                using (FileStream FileReader = new FileStream(FullFileName, FileMode.Open, FileAccess.Read))
                {
                    FromStreamToStream(FileReader, Response.OutputStream);
  
                    Response.OutputStream.Close();
                }

                Response.End();
                return;
            }
            else
            {
                List<FileResponse> FileResponseList = new List<FileResponse>();

                string[] FileNames = Directory.GetFiles(FilesPath);

                foreach (string FileName in FileNames)
                {
                    FileResponseList.Add(CreateFileResponse(FileName, new FileInfo(FileName).Length, String.Empty));
                }

                SerializeUploaderResponse(FileResponseList);
            }            
        }
        else if (Request.HttpMethod.ToUpper() == HttpMethods.POST)
        {
            List<FileResponse> FileResponseList = new List<FileResponse>();
            
            for (int FileIndex = 0; FileIndex < Request.Files.Count; FileIndex++)
            {
                HttpPostedFile File = Request.Files[FileIndex];

                string FileName = String.Format(@"{0}\{1}", FilesPath, Path.GetFileName(File.FileName));
                string ErrorMessage = String.Empty;
                
                for (int Attempts = 0; Attempts < ATTEMPTS_TO_WRITE; Attempts++)
                {
                    ErrorMessage = String.Empty;

                    if (System.IO.File.Exists(FileName))
                    {
                        FileName = String.Format(@"{0}\{1}_{2:yyyyMMddHHmmss.fff}{3}", FilesPath, Path.GetFileNameWithoutExtension(FileName), DateTime.Now, Path.GetExtension(FileName));
                    }
                    
                    try
                    {
                        using (Stream FileStreamWriter = new FileStream(FileName, FileMode.CreateNew, FileAccess.Write))
                        {
                            FromStreamToStream(File.InputStream, FileStreamWriter);
                        }
                    }
                    catch (Exception exception)
                    {
                        ErrorMessage = exception.Message;
                        System.Threading.Thread.Sleep(ATTEMPT_WAIT);
                        continue;
                    }
 
                    break;
                }

                FileResponseList.Add(CreateFileResponse(File.FileName, File.ContentLength, ErrorMessage));
            }

            SerializeUploaderResponse(FileResponseList);
        }
        else if (Request.HttpMethod.ToUpper() == HttpMethods.DELETE)
        {
            bool SuccessfullyDeleted = true;          
            
            try
            {
                File.Delete(FullFileName);
            }
            catch
            {
                SuccessfullyDeleted = false;
            }

            Response.Write(String.Format("{{\"{0}\":{1}}}", ShortFileName, SuccessfullyDeleted.ToString().ToLower()));            
        }
        else
        {
            Response.StatusCode = 405;
            Response.StatusDescription = "Method not allowed";
            Response.End();

            return;
        }

        
        Response.End();
    }   
</script>

这是演示.js

$(function() {
  'use strict';

  // Initialize the jQuery File Upload widget:
  $('#fileupload').fileupload({
    // Uncomment the following to send cross-domain cookies:
    //xhrFields: {withCredentials: true},
      url: 'server/asp_net/UploadHandler_4_0.aspx'
  });

  // Enable iframe cross-domain access via redirect option:
  $('#fileupload').fileupload(
    'option',
    'redirect',
    window.location.href.replace(/\/[^/]*$/, '/cors/result.html?%s')
  );

  if (window.location.hostname === 'blueimp.github.io') {
    // Demo settings:
    $('#fileupload').fileupload('option', {
      url: '//jquery-file-upload.appspot.com/',
      // Enable image resizing, except for Android and Opera,
      // which actually support image resizing, but fail to
      // send Blob objects via XHR requests:
      disableImageResize: /Android(?!.*Chrome)|Opera/.test(
        window.navigator.userAgent
      ),
      maxFileSize: 999000,
      acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i
    });
    // Upload server status check for browsers with CORS support:
    if ($.support.cors) {
      $.ajax({
        url: '//jquery-file-upload.appspot.com/',
        type: 'HEAD'
      }).fail(function() {
        $('<div class="alert alert-danger"/>')
          .text('Upload server currently unavailable - ' + new Date())
          .appendTo('#fileupload');
      });
    }
  } else {
    // Load existing files:
    $('#fileupload').addClass('fileupload-processing');
    
    console.log($('#fileupload').fileupload('option', 'url'));
    
    $.ajax({
      // Uncomment the following to send cross-domain cookies:
      //xhrFields: {withCredentials: true},
      url: $('#fileupload').fileupload('option', 'url'),
      dataType: 'json',
      context: $('#fileupload')[0]
    })
      .always(function() {
        $(this).removeClass('fileupload-processing');
      })
      .done(function(result) {
        $(this)
          .fileupload('option', 'done')
          // eslint-disable-next-line new-cap
          .call(this, $.Event('done'), { result: result });
      });
  }
});
javascript jquery asp.net blueimp

评论


答: 暂无答案