相机照片未添加到ios设备的文件输入



我在Blazor wasm中创建了一个文件上传区域组件。这是视图

<div @ref="@this.UploadContainer" class="uploadContainer text-black-50" tabindex="0">
<Icon Name="IconName.Paperclip" />
<Paragraph>
@this.Localizer["DragAndDropFiles"]
</Paragraph>
<Paragraph>
@string.Join(" | ", this.Files.Select(file => file.Name))
</Paragraph>
<InputFile @ref="@this.InputFile"
OnChange="this.OnChange"
style="display: none;" multiple />
</div>

我使用Blazorise组件的地方。视图

背后的代码
public partial class FileUploadArea
: IAsyncDisposable
{
[Inject]
public IJSRuntime JsRuntime { get; set; } = null!;
[Inject]
public IStringLocalizer<App> Localizer { get; set; } = null!;
[Parameter]
public List<IBrowserFile> Files { get; set; } = new List<IBrowserFile>();
[Parameter]
public bool Disabled { get; set; }
private ElementReference UploadContainer { get; set; }
private InputFile? InputFile { get; set; } = null!;
private IJSObjectReference? JsModule { get; set; }
private IJSObjectReference? FileUploadModule { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
this.JsModule = await this.JsRuntime.InvokeAsync<IJSObjectReference>("import", new object[] { "./js/fileUploadArea.js" });
this.FileUploadModule = await this.JsModule.InvokeAsync<IJSObjectReference>("initializeFileDropZone", this.UploadContainer, this.InputFile!.Element);
}
await base.OnAfterRenderAsync(firstRender);
}
private void OnChange(InputFileChangeEventArgs e)
{
if (this.Disabled)
{
return;
}
this.Files.Clear();
this.Files.AddRange(e.GetMultipleFiles(10));
this.StateHasChanged();
}
public async ValueTask DisposeAsync()
{
if (this.FileUploadModule is not null)
{
await this.FileUploadModule.InvokeVoidAsync("dispose");
}
}
}

这是视图的css(如果它是相关的…)

。uploadContainer {边框样式:虚线;边框宽度:3 px;边框颜色:lightgrey;text-align:中心;填充:3他们;border - radius: 1 em;大纲:没有;光标:指针;}.uploadContainer。{徘徊边框样式:固体;}

这里是让它工作的javascript代码

export function initializeFileDropZone(dropZoneElement, inputFile) {
function onClick(e) {
e.preventDefault();
let input = document.createElement('input');
input.type = inputFile.type;
input.accept = inputFile.accept
input.multiple = inputFile.multiple;
input.onchange = e => {
inputFile.files = e.target.files;
const event = new Event('change', { bubbles: true });
inputFile.dispatchEvent(event);
}
input.click();
}
function onDragHover(e) {
e.preventDefault();
dropZoneElement.classList.add("hover");
}
function onDragLeave(e) {
e.preventDefault();
dropZoneElement.classList.remove("hover");
}

function onDrop(e) {
e.preventDefault();
dropZoneElement.classList.remove("hover");
inputFile.files = e.dataTransfer.files;
const event = new Event('change', { bubbles: true });
inputFile.dispatchEvent(event);
}
function onPaste(e) {
inputFile.files = e.clipboardData.files;
const event = new Event('change', { bubbles: true });
inputFile.dispatchEvent(event);
}
// Register all events
dropZoneElement.addEventListener("click", onClick);
dropZoneElement.addEventListener("dragenter", onDragHover);
dropZoneElement.addEventListener("dragover", onDragHover);
dropZoneElement.addEventListener("dragleave", onDragLeave);
dropZoneElement.addEventListener("drop", onDrop);
dropZoneElement.addEventListener('paste', onPaste);
// The returned object allows to unregister the events when the Blazor component is destroyed
return {
dispose: () => {
dropZoneElement.removeEventListener("click", onClick);
dropZoneElement.removeEventListener('dragenter', onDragHover);
dropZoneElement.removeEventListener('dragover', onDragHover);
dropZoneElement.removeEventListener('dragleave', onDragLeave);
dropZoneElement.removeEventListener("drop", onDrop);
dropZoneElement.removeEventListener('paste', onPaste);
}
}
}

页面上的输入是隐藏的,因此在上传区域是可见的。点击上传区域是由javascript处理,它创建一个新的文件输入与隐藏的一个相同的参数,并打开它,然后将文件传输到隐藏的文件输入,所以onchange甚至从后面的代码被触发。

这在PC和Android设备上工作得很好,但在iPhone和iPad上,相机打开,但拍摄的任何照片都不会传递给隐藏输入的onChange。我怎样才能使这个功能在所有设备上与相机一致呢?

经过一番研究,我找到了一个解决方案。通过在文件输入元素的标签中包装UploadContainerdiv,可以省去js的单击处理程序。标签将点击重定向到文件输入元素,而重定向点击事件并明显导致问题的js代码则消失了。

新的视图看起来像这样

<Label For="@fileUploadId"
Style="width: 100%;">
<div @ref="@this.UploadContainer" class="uploadContainer text-black-50" tabindex="0">
<Icon Name="IconName.Paperclip" />
<Paragraph>
@this.Localizer["DragAndDropFiles"]
</Paragraph>
<Paragraph>
@string.Join(" | ", this.Files.Select(file => file.Name))
</Paragraph>
<InputFile id="@fileUploadId"
@ref="@this.InputFile"
OnChange="this.OnChange"
style="display: none;"
multiple />
</div>
</Label>

,其中@fileUploadId是后面代码中的静态字符串。

在台式机、iPad、Safari和iPhone上都可以正常运行。

最新更新