41

我有一个图片上传按钮,当从浏览窗口中选择时会自动上传文件。
尽管如此,它第二次不起作用,那是因为未触发 onChange 事件。为什么呢?

这是一个用例:
1. 单击按钮时,我调用uploadMessagePicture(),它会打开浏览窗口。
2. 当用户选择了一张图片时,会检测到一个 onChange 事件,该事件会触发 ajaxFileUpload() 并显示照片编辑器区域。
3. 上传完成后,会显示图片预览。4. 用户通过调用 deleteMessageImage() 删除图片(同时清除字段并隐藏照片编辑器)。
5. 用户尝试上传另一张图片。

此时会出现浏览窗口,但是当我选择图片时,不会触发 onChange 事件,因此什么也没有发生……(而且,文件名似乎甚至没有传输到输入的值字段。)
我在 Firefox 23.0.1

这是HTML:

<a class="im-photo-btn" href="javascript:;" onclick="javascript:uploadMessagePicture();"><i class="icon-join-photo"></i></a>

<div class="editor-photoarea" id="editor-photoarea" style="display:none;">
    <input name="image_message_file" type="hidden" id="image_message_file" value="" />
    <div id="image_message_upload">
        <input name="image-message" type="file" id="image-message" style="display:none; visibility:hidden;" /> 
        <!-- hide it and trigger it from the photo btn (need both display:none + visibility:hiden for browser compatibility) -->
    </div>
    <div class="loading" id="image_message_loading" style="display:none;"><img alt="<?php echo $lang["Loading"];?>" src="lib/immedia/img/ajax-loader.gif" /> <?php echo $lang["Loading"];?></div>
    <div class="preview" style="display:none;" id="image_message_preview">
        <!-- <div>Image preview :</div>
        <div id='small_message_msg'></div>
            <img src='' />
            <div class='btnoptions'>
                <a onclick='javascript:deleteMessageImage();' href='javascript:;' class='button' title="Delete photo">
                    <span class='ui-icon ui-icon-closethick smsg'></span>Delete
                </a>
         </div>-->
</div>

这是自动上传图片的javascript

$(document).ready(function (){
    $("#image-message").on('change', function () {
        $('#editor-photoarea').show();
        ajaxFileUploadMessagePicture();
    });
});

function uploadMessagePicture(){
    //trigger the browse click
    if($('#image_message_file').val() == ''){
        //let the person upload a file only if none are there
        $('#image-message').trigger('click');
    }
}

function ajaxFileUploadMessagePicture(){
$("#msg_error_no_image_message").hide();

var imageName = $("#image-message").val();
if(imageName != ''){
    $("#image_message_loading").show();
    $('#sendBtn').attr('disabled', 'disabled');

    $.ajaxFileUpload
    (
        {
            url:siteRegionDir+'lib/immedia/uploadMessagePicture.php',
            secureuri:false,
            fileElementId:'image-message',
            dataType: 'json',
            success: function (data, status)
            {
                updateMessagePicture(data);             
            },
            error: function (data, status, e)
            {
                alert(e);
            }
        }
    )   
}else{
    $("#msg_error_no_image_message").show();
}
return false;
}

这是删除图片并清除字段的Javascript

function deleteMessageImage(){
//delete the image
var file = $("#image_message_file").val();

if(file != '') {
    $.post(siteRegionDir+'lib/immedia/deleteMessagePicture.php',{filename:file}, function(data) {   
            clearPictureAttachment();               
            $('#editor-photoarea').hide();//make sure it is hidden
        },"html"  
    );
}else{      
    clearPictureAttachment();
    $('#editor-photoarea').hide();//make sure it is hidden
}
}

function clearPictureAttachment(){
//var control = $("#image-message");
$("#image-message").attr('value', '');
//control.replaceWith( control = control.clone( true ) );//so it resets it all, truw = keep the bound events
$("#image_message_file").attr('value', '');
$("#image_message_loading").hide();
$("#image_message_upload").show();
$("#image_message_preview").hide();
}

任何帮助都会很棒!谢谢!

4

10 回答 10

64

如果您使用的是 React 或一般只是 javascript,您还可以做的是“重置”事件目标的值。

因此,如果您有类似可以上传和“删除”图像的组件:

<input type="file" onChange={onChange} />

onChange可以是:

onChange(event) {

    const files = event.target.files;

    // your logic here on what to do with files (maybe fetch the preview or something)

    // this line right below will reset the 
    // input field so if you removed it you can re-add the same file
    event.target.value = ''
}
于 2019-05-22T14:15:01.343 回答
15

我的猜测是您一遍又一遍地使用相同的图片文件测试您的功能。

如果选择同一个文件,input[type=file]不会触发 onChange 事件。

具有相同名称的不同文件也不会触发该事件。选择一个不同的图像文件 - 它会发生。

为避免这种情况,您可以重置表单以确保选择文件将在干净的file控件上执行

于 2013-11-12T18:27:01.687 回答
12

TL;DR:只需在使用文件选择器后立即将 value 属性重置为 empty("")(使用一些事件回调或显式函数调用)

关于 onchange 事件,同步部分是正确的,它不会为同一个文件触发。更准确地说,在输入类型文件(ether提到的场景)的情况下,onchange 考虑了事件触发的文件位置。

##在jQuery中选择任何文件后试试这个 $("#image_message_upload [type='file']")[0].value

您将得到类似“ C:\fakepath\country-and-mobile-redirect-for-wordpress-dwpsxm-clipar.jpg ”的输出(即所选文件的位置)

这意味着您要么更改文件名,要么更改其位置,这是不对的。因此,更合乎逻辑的是,我们在删除文件时可以做的是将输入值属性设置为空(“”

$("#image_message_upload [type='file']")[0].value=""

因此,添加这一行(在 clearPictureAttachment() 中,根据这个问题)将重置文件输入类型,您可以毫无问题地选择相同的图像文件。

干杯:)

于 2016-12-29T14:48:45.797 回答
6

感谢codingrhythm 引导我走上正轨。
我所做的实际上只是在现场再次添加 on("change") 调用。
所以我只将 clearPictureAttachment() 函数(删除图片时调用)更改为:

function clearPictureAttachment(){
$("#image-message").attr('value', '');    
$("#image_message_file").attr('value', '');
$("#image_message_loading").hide();
$("#image_message_upload").show();
$("#image_message_preview").hide();
//reenable the onchange to upload a picture
$("#image-message").on('change', function () {
    $('#editor-photoarea').show();
    ajaxFileUploadMessagePicture();
});
}

再次感谢!

于 2014-10-01T18:28:43.660 回答
4

@Sync 给了我解决这个问题的想法。

这是工作代码,您需要做的是克隆文件输入。

var control = $('input[type=file]');
control.replaceWith( control = control.clone( true ) );

并且该事件仍将在第二次触发。

于 2014-07-13T23:27:59.233 回答
4

在角度

HTML

<input #photoInput type="file" /> 

TS

export class SomeComponent {

 @ViewChild('photoInput') photoInput;

 clearPictureAttachment() {
  this.photoInput.nativeElement.value = '';
 }
}
于 2018-01-25T12:05:16.443 回答
4

解决此问题的最简单方法是添加一个 onclick 并将值设置为 null 每次。:

<input name="fileUpload" type="file" onclick="this.value = null"/>
于 2020-10-21T20:49:19.027 回答
0

完成您想要对文件执行的操作后,您可以重置 FileList。

在我的 React 应用程序中,我有这个:

const handleLoad = evt => {
  if (evt.target.files && evt.target.files[0]) {
    dispatch(loadFile(evt.target.files[0].path));
  }
  // Reset the FileList, as otherwise the second and subsequent times
  // we browse, nothing will happen, because nothing changed.
  evt.target.files = new FileList();
};
于 2019-10-27T21:47:47.543 回答
0

如果您使用的是 Angular,以下将是最简单的:
<input (change)="setImageValue($event)" (click)="inputImage.value = ''" accept=".jpg, .jpeg, .png" class="file" #inputImage type="file">

于 2021-10-31T13:28:24.580 回答
0

只是因为没有改变的准确性。

你应该在你的代码结束时重置它:

$("#image-message").val("");
于 2021-11-02T09:31:07.780 回答