有人可以解释如何实现jQuery文件上传插件吗?

时间:2013-07-29 21:38:48

标签: jquery file-upload jquery-plugins jquery-file-upload

编辑:

这似乎仍然有流量,所以我会解释我最终做的事情。 我最终通过遵循Subrat的教程得到了插件,这是接受的答案。但是,jQuery文件上传真的很麻烦,如果你正在寻找一个简单的文件上传插件,我强烈推荐Uploadify(谢谢,CORSAIR!)。正如答案所指出的那样,它只是免费用于非商业用途。

背景

我正在尝试使用blueimp的jQuery File Upload来允许用户上传文件。 按照设置说明,开箱即用。但是为了在我的网站上实际使用它,我希望能够做一些事情:

  • 在我现有的任何网页上添加上传者
  • 更改上传文件的目录

该插件的所有文件都位于根目录下的文件夹中。

我试过......

  • 将演示页移动到根目录并更新必要脚本的路径
  • 按建议here更改UploadHandler.php文件中的'upload_dir'和'upload_url'选项。
  • 更改演示javascript第二行中的网址

在所有情况下,预览显示,进度条运行,但文件无法上传,我在控制台中收到此错误:Uncaught TypeError: Cannot read property 'files' of undefined。我不明白插件的所有部分是如何工作的,这使得调试变得困难。

代码

演示页面中的javascript:

$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = 'file_upload/server/php/UploadHandler.php',
    uploadButton = $('<button/>')
        .addClass('btn')
        .prop('disabled', true)
        .text('Processing...')
        .on('click', function () {
            var $this = $(this),
                data = $this.data();
            $this
                .off('click')
                .text('Abort')
                .on('click', function () {
                    $this.remove();
                    data.abort();
                });
            data.submit().always(function () {
                $this.remove();
            });
        });
$('#fileupload').fileupload({
    url: url,
    dataType: 'json',
    autoUpload: false,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    maxFileSize: 5000000, // 5 MB
    // 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),
    previewMaxWidth: 100,
    previewMaxHeight: 100,
    previewCrop: true
}).on('fileuploadadd', function (e, data) {
    data.context = $('<div/>').appendTo('#files');
    $.each(data.files, function (index, file) {
        var node = $('<p/>')
                .append($('<span/>').text(file.name));
        if (!index) {
            node
                .append('<br>')
                .append(uploadButton.clone(true).data(data));
        }
        node.appendTo(data.context);
    });
}).on('fileuploadprocessalways', function (e, data) {
    var index = data.index,
        file = data.files[index],
        node = $(data.context.children()[index]);
    if (file.preview) {
        node
            .prepend('<br>')
            .prepend(file.preview);
    }
    if (file.error) {
        node
            .append('<br>')
            .append(file.error);
    }
    if (index + 1 === data.files.length) {
        data.context.find('button')
            .text('Upload')
            .prop('disabled', !!data.files.error);
    }
}).on('fileuploadprogressall', function (e, data) {
    var progress = parseInt(data.loaded / data.total * 100, 10);
    $('#progress .bar').css(
        'width',
        progress + '%'
    );
}).on('fileuploaddone', function (e, data) {
    $.each(data.result.files, function (index, file) {
        var link = $('<a>')
            .attr('target', '_blank')
            .prop('href', file.url);
        $(data.context.children()[index])
            .wrap(link);
    });
}).on('fileuploadfail', function (e, data) {
    $.each(data.result.files, function (index, file) {
        var error = $('<span/>').text(file.error);
        $(data.context.children()[index])
            .append('<br>')
            .append(error);
    });
}).prop('disabled', !$.support.fileInput)
    .parent().addClass($.support.fileInput ? undefined : 'disabled');
});

<小时/> 缺乏文件令我感到惊讶;似乎改变应该是一件简单的事情。如果有人能解释如何做到这一点,我将不胜感激。

11 个答案:

答案 0 :(得分:66)

几天前我一直在寻找类似的功能,并且遇到了一个关于tutorialzine的好教程。这是一个有效的例子。完整的教程可以找到here

用于保存文件上传对话框的简单表单:

<form id="upload" method="post" action="upload.php" enctype="multipart/form-data">
  <input type="file" name="uploadctl" multiple />
  <ul id="fileList">
    <!-- The file list will be shown here -->
  </ul>
</form>

这是上传文件的jQuery代码:

$('#upload').fileupload({

  // This function is called when a file is added to the queue
  add: function (e, data) {
    //This area will contain file list and progress information.
    var tpl = $('<li class="working">'+
                '<input type="text" value="0" data-width="48" data-height="48" data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" />'+
                '<p></p><span></span></li>' );

    // Append the file name and file size
    tpl.find('p').text(data.files[0].name)
                 .append('<i>' + formatFileSize(data.files[0].size) + '</i>');

    // Add the HTML to the UL element
    data.context = tpl.appendTo(ul);

    // Initialize the knob plugin. This part can be ignored, if you are showing progress in some other way.
    tpl.find('input').knob();

    // Listen for clicks on the cancel icon
    tpl.find('span').click(function(){
      if(tpl.hasClass('working')){
              jqXHR.abort();
      }
      tpl.fadeOut(function(){
              tpl.remove();
      });
    });

    // Automatically upload the file once it is added to the queue
    var jqXHR = data.submit();
  },
  progress: function(e, data){

        // Calculate the completion percentage of the upload
        var progress = parseInt(data.loaded / data.total * 100, 10);

        // Update the hidden input field and trigger a change
        // so that the jQuery knob plugin knows to update the dial
        data.context.find('input').val(progress).change();

        if(progress == 100){
            data.context.removeClass('working');
        }
    }
});
//Helper function for calculation of progress
function formatFileSize(bytes) {
    if (typeof bytes !== 'number') {
        return '';
    }

    if (bytes >= 1000000000) {
        return (bytes / 1000000000).toFixed(2) + ' GB';
    }

    if (bytes >= 1000000) {
        return (bytes / 1000000).toFixed(2) + ' MB';
    }
    return (bytes / 1000).toFixed(2) + ' KB';
}

以下是处理数据的PHP代码示例:

if($_POST) {
    $allowed = array('jpg', 'jpeg');

    if(isset($_FILES['uploadctl']) && $_FILES['uploadctl']['error'] == 0){

        $extension = pathinfo($_FILES['uploadctl']['name'], PATHINFO_EXTENSION);

        if(!in_array(strtolower($extension), $allowed)){
            echo '{"status":"error"}';
            exit;
        }

        if(move_uploaded_file($_FILES['uploadctl']['tmp_name'], "/yourpath/." . $extension)){
            echo '{"status":"success"}';
            exit;
        }
        echo '{"status":"error"}';
    }
    exit();
}

上述代码可以添加到任何现有表单中。添加后,该程序会自动上传图像。您可以在提交现有表单时更改此功能并提交图像。

使用实际代码更新了我的答案。所有学分均为原作者。

来源: http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/

答案 1 :(得分:25)

我刚刚花了2个小时与jQuery上传进行斗争,但由于依赖程序的数量而放弃了(我有13个JS文件可以获得所有的花里胡哨)。

我做了一些搜索,遇到了一个名为Dropzone.js的整洁项目,该项目没有任何依赖项。

作者还创建了一个受{jQuery File Upload插件启发的bootstrap demo

我希望这能节省一些时间。

答案 2 :(得分:4)

我也在努力解决这个问题,但是一旦我弄清楚路径在UploadHandler.php中是如何工作的,它就能让它工作:upload_dir和upload_url是关于让它工作的唯一设置。另请检查服务器错误日志以获取调试信息。

答案 3 :(得分:3)

使用dropper jquery插件查看带有图像预览的图像拖放上传器。

<强> HTML

<div class="target" width="78" height="100"><img /></div>

<强> JS

$(".target").dropper({
    action: "upload.php",

}).on("start.dropper", onStart);
function onStart(e, files){
console.log(files[0]);

    image_preview(files[0].file).then(function(res){
$('.dropper-dropzone').empty();
//$('.dropper-dropzone').css("background-image",res.data);
 $('#imgPreview').remove();        
$('.dropper-dropzone').append('<img id="imgPreview"/><span style="display:none">Drag and drop files or click to select</span>');
var widthImg=$('.dropper-dropzone').attr('width');
        $('#imgPreview').attr({width:widthImg});
    $('#imgPreview').attr({src:res.data});

    })

}

function image_preview(file){
    var def = new $.Deferred();
    var imgURL = '';
    if (file.type.match('image.*')) {
        //create object url support
        var URL = window.URL || window.webkitURL;
        if (URL !== undefined) {
            imgURL = URL.createObjectURL(file);
            URL.revokeObjectURL(file);
            def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
        }
        //file reader support
        else if(window.File && window.FileReader)
        {
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onloadend = function () {
                imgURL = reader.result;
                def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
            }
        }
        else {
            def.reject({status: 1001, message: 'File uploader not supported', data:imgURL, error: {}});
        }
    }
    else
        def.reject({status: 1002, message: 'File type not supported', error: {}});
    return def.promise();
}

$('.dropper-dropzone').mouseenter(function() {
 $( '.dropper-dropzone>span' ).css("display", "block");
});

$('.dropper-dropzone').mouseleave(function() {
 $( '.dropper-dropzone>span' ).css("display", "none");
});

<强> CSS

.dropper-dropzone{
    width:78px;
padding:3px;
    height:100px;
position: relative;
}
.dropper-dropzone>img{
    width:78px;
    height:100px;
margin-top=0;
}

.dropper-dropzone>span {
    position: absolute;
    right: 10px;
    top: 20px;
color:#ccc;


}

.dropper .dropper-dropzone{

padding:3px !important    
}

Demo Jsfiddle

答案 4 :(得分:2)

这是一个很好的Angular插件,用于上传文件,它是免费的!

angular file upload

答案 5 :(得分:1)

我在这个插件上挣扎了一段时间在Rails上,然后有人把它搞砸了我已经创建的所有代码。

虽然看起来你没有在Rails中使用它,但是如果有人使用它,请查看此gem。来源在这里 - &gt; jQueryFileUpload Rails

更新:

为了满足评论者的需求,我更新了答案。基本上是“use this gemhere is the source code”如果它消失了,那么就这么做了。

答案 6 :(得分:1)

你好试试波纹管链接很容易。我被困了很长时间,它在几分钟内解决了我的问题。 http://simpleupload.michaelcbrook.com/#examples

答案 7 :(得分:1)

Droply.js对此非常适合。它很简单,并且预先打包了一个演示站点,可以直接使用。

答案 8 :(得分:1)

现在是 2021 年,这里有一个非常简单的插件可以上传任何东西:

https://pqina.nl/filepond/?ref=pqina

添加您的元素:

<input type="file" 
class="filepond"
name="filepond" 
multiple 
data-allow-reorder="true"
data-max-file-size="3MB"
data-max-files="3">

注册任何其他插件:

  FilePond.registerPlugin(
FilePondPluginImagePreview,  
FilePondPluginImageExifOrientation,  
FilePondPluginFileValidateSize,  
FilePondPluginImageEdit);

然后在元素中连线:

// Select the file input and use 
// create() to turn it into a pond
FilePond.create(
  document.querySelector('input'),

  // Use Doka.js as image editor
  imageEditEditor: Doka.create({
    utils: ['crop', 'filter', 'color']
  })
);

我将它与额外的 Doka 图像编辑器一起用于在 https://www.yoodu.co.uk

上传和转换图像

设置非常简单,运行它的人非常擅长支持。

正如你所知道的,我是个粉丝。

答案 9 :(得分:0)

您可以使用uploadify 这是我用过的最好的multiupload jquery插件。

实施简单,浏览器支持完善。

答案 10 :(得分:0)

对于UI插件,使用jsp页面和Spring MVC ..

示例 html 。需要位于形式元素中 id 属性为 fileupload

    @PostMapping("/app/uploadResources")
public @ResponseBody
Map<String, List<FileUploadResponse>> uploadResources(MultipartHttpServletRequest request,
        Locale locale) {
    //https://github.com/jdmr/fileUpload/blob/master/src/main/java/org/davidmendoza/fileUpload/web/ImageController.java
    //https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
    Map<String, List<FileUploadResponse>> response = new HashMap<>();
    List<FileUploadResponse> fileList = new ArrayList<>();

    String deleteUrlBase = request.getContextPath() + "/app/deleteResources.do?filename=";

    //http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartRequest.html
    Iterator<String> itr = request.getFileNames();
    while (itr.hasNext()) {
        String htmlParamName = itr.next();
        MultipartFile file = request.getFile(htmlParamName);
        FileUploadResponse fileDetails = new FileUploadResponse();
        String filename = file.getOriginalFilename();
        fileDetails.setName(filename);
        fileDetails.setSize(file.getSize());
        try {
            String message = saveFile(file);
            if (message != null) {
                String errorMessage = messageSource.getMessage(message, null, locale);
                fileDetails.setError(errorMessage);
            } else {
                //save successful
                String encodedFilename = URLEncoder.encode(filename, "UTF-8");
                String deleteUrl = deleteUrlBase + encodedFilename;
                fileDetails.setDeleteUrl(deleteUrl);
            }
        } catch (IOException ex) {
            logger.error("Error", ex);
            fileDetails.setError(ex.getMessage());
        }

        fileList.add(fileDetails);
    }

    response.put("files", fileList);

    return response;
}

@PostMapping("/app/deleteResources")
public @ResponseBody
Map<String, List<Map<String, Boolean>>> deleteResources(@RequestParam("filename") List<String> filenames) {
    Map<String, List<Map<String, Boolean>>> response = new HashMap<>();
    List<Map<String, Boolean>> fileList = new ArrayList<>();

    String templatesPath = Config.getTemplatesPath();
    for (String filename : filenames) {
        Map<String, Boolean> fileDetails = new HashMap<>();

        String cleanFilename = ArtUtils.cleanFileName(filename);
        String filePath = templatesPath + cleanFilename;

        File file = new File(filePath);
        boolean deleted = file.delete();

        if (deleted) {
            fileDetails.put(cleanFilename, true);
        } else {
            fileDetails.put(cleanFilename, false);
        }

        fileList.add(fileDetails);
    }

    response.put("files", fileList);

    return response;
}

示例上传和删除请求处理程序

    public class FileUploadResponse {
    //https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler

    private String name;
    private long size;
    private String error;
    private String deleteType = "POST";
    private String deleteUrl;

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return the size
     */
    public long getSize() {
        return size;
    }

    /**
     * @param size the size to set
     */
    public void setSize(long size) {
        this.size = size;
    }

    /**
     * @return the error
     */
    public String getError() {
        return error;
    }

    /**
     * @param error the error to set
     */
    public void setError(String error) {
        this.error = error;
    }

    /**
     * @return the deleteType
     */
    public String getDeleteType() {
        return deleteType;
    }

    /**
     * @param deleteType the deleteType to set
     */
    public void setDeleteType(String deleteType) {
        this.deleteType = deleteType;
    }

    /**
     * @return the deleteUrl
     */
    public String getDeleteUrl() {
        return deleteUrl;
    }

    /**
     * @param deleteUrl the deleteUrl to set
     */
    public void setDeleteUrl(String deleteUrl) {
        this.deleteUrl = deleteUrl;
    }

}

用于生成所需json响应的示例类

this.page.identifier

请参阅https://pitipata.blogspot.co.ke/2017/01/using-jquery-file-upload-ui.html