Ответ 1
FileReader
load
событие устанавливает значение .result
асинхронно. Чтобы получить доступ к .result
, используйте событие load
или loadend
.
Когда файл был выбран в <input type="file">
Choose File
или Browse...
пользовательском интерфейсе, удаление файла в локальной файловой системе не должно влиять на объект File
на FileList
, возвращаемый вызовом .files
. См. 2.9.2. Переносимые объекты, 6.7.3 Интерфейс DataTransfer.
4. Интерфейс Blob и двоичные данные
Каждый
Blob
должен иметь внутреннее состояние моментального снимка, которое должно быть изначально установлено в состояние базового хранилища, если оно такое базовое хранилище существует и должно быть сохранено черезstructured clone
. Дальнейшее нормативное определениеsnapshot state
можно найти дляFile
с.
2.9.8 Патч Monkey для объектов Blob и FileList
Этот патч обезьяны будет удален со временем. См. w3c/FileAPI вопрос 32.
Blob
объектыcloneable objects
.
Каждый объект
Blob
object [[Clone
]] внутренний метод, заданный targetRealm и игнорирующий память, должен запускать эти шаги:Если это
closed
, тогда выпустите"DataCloneError"
DOMException
.Возвращает новый экземпляр этого в targetRealm, соответствующий те же базовые данные.
FileList
объекты клонируемые объекты.Каждый
FileList
объект[[Clone]]
внутренний метод, данный targetRealm и память, должны выполнить следующие шаги:
Пусть output будет новым объектом
FileList
в targetRealm.Для каждого файла в этом, добавьте?
[StructuredClone][15](_file, targetRealm, memory_)
в конец спискаFile
объектов вывода.Возвратный вывод.
Выбор файлов или папок только для чтения в браузерах webkit и firefox
В chrome, chromium, если разрешено только чтение для файла в локальной файловой системе, и пользователь выбирает файл в элементе <input type="file">
, где FileReader
используется для чтения файла, ошибка генерируется при FileReader
, сгенерированной из FileReader
progress
событие.
Если a Blob URL
установлен в один и тот же файл-объект, URL blob:
не будет возвращать файл только для чтения по запросу Blob URL
.
Выбор папки, в которой разрешено разрешение на доступ к папке
Chrome, хром
В chrome, chromium, где установлен атрибут webkitdirectory
, и папка выбрана с разрешением только для чтения FileList
.length
of event.target.files
return 0
; event.target.files.webkitGetAsEntry()
не вызывается, "No file chosen"
отображается в <input type="file">
shadowDOM
. Когда папка удаляется в <input type="file">
или элементе, где установлен атрибут droppable
, каталог .name
и .path
только для чтения отображается в drop
event.dataTransfer
.
Когда пользователь отбрасывает файл или папку в элементе <textarea>
, где не подключено событие drop
beforeunload
вызывается событие, а prompr отображается в интерфейсе пользователя
Do you want to leave this site? Changes you made may not be saved. <Stay><Leave> // <buttons>
Firefox
В версии firefox 47.0b9 с атрибутом allowdirs
установлено значение <input type="file">
, где пользователь нажимает "Choose folder.."
<input>
, папки .name
и .path
родительской папки доступны в .then()
прикован к event.target.getFilesAndDirectories()
. Файлы или папки, содержащиеся в выбранной папке, не возвращаются при рекурсивном итерации записей Directory
; возвращается пустая строка.
Если пользователь нажимает "Choose file..."
<input>
и папка выбрана без разрешения только для чтения, при нажатии папки в диспетчере файлов отображаются файлы в папке.
Если выбрана папка, где установлено разрешение только для чтения, уведомление об уведомлении alert()
отображается при отображении пользовательского интерфейса
Could not read the contents of <directory name> Permission denied
Ошибка, проблема с безопасностью
* nix OS
Когда пользователь отбрасывает папку в элементе <textarea>
, где не подключено событие drop
, отображается полный путь к папке в пользовательской файловой системе file:
. Пути к файлам, содержащимся в папке, также не устанавливаются как .value
; например.
"file:///home/user/Documents/Document/"
Когда файл отбрасывается в элементе <textarea>
, где не подключено событие drop
, полный путь к файлу в пользовательской файловой системе устанавливается как .value
из <textarea>
; то есть
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.txt"
Если несколько файлов выбраны и сброшены в элементе <textarea>
, все полные пути к файлу будут установлены как .value
из <textarea>
, обозначены символом новой строки \n
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue1.txt"
"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue2.txt"
..
Где XMLHttpRequest()
делается для пути к файлу, и ошибка регистрируется в console
NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
При установке .src
элемента <img>
с .crossOrigin
, установленного в "anonymous"
обработчик события img
error
, называется
При вызове window.open()
с полным набором путей при первом параметре
Error: Access to '"file:///home/user/Documents/Document/MyFileFullPathDisplayedAtTextAreaValue.png"' from script denied
Спецификация
4.10.5.1.18. Состояние загрузки файла (type=file
)
По историческим причинам атрибут IDL
value
префикс имя файла со строкой "C:\fakepath\
". Некоторые устаревшие пользовательские агенты фактически включал полный путь (который был уязвимостью безопасности). В результате этого, получив имя файла изvalue
IDL атрибут с обратной совместимостью является нетривиальным.
4.10.5.4. Общие <input>
API-интерфейсы элементов
имя файла
При получении он должен вернуть строку "C:\fakepath", а затем имя первого файла в списке
selected files
, если есть, или пустую строку, если список пуст. На если новое значение является пустой строкой, оно должно удалить список отselected files
; в противном случае он должен выбросить "InvalidStateError
"DOMException
.ПРИМЕЧАНИЕ. Это требование "фальшивого пути" - печальная случайность истории. См. Пример в разделе состояния Загрузка файлов для более подробной информации. информация.
ПРИМЕЧАНИЕ: Так как
path components
не разрешены в именах файлов в спискеselected files
, "\fakepath\
" не может быть ошибочно для компонента пути.
4.10.5.1.18. Состояние загрузки файла (type=file
)
Компоненты пути
Если атрибут
<input>
type
находится вFile Upload
, применяются правила в этом разделе.Элемент
<input>
represents
списокselected files
, каждый файл, состоящий из имени файла, типа файла и тела файла ( содержимое файла).Имена файлов не должны содержать
path components
даже в том случае, если пользователь выбрал целую иерархию каталогов или несколько файлов с одно и то же имя из разных каталогов. Компоненты пути, для целей состоянияFile Upload
, являются те части имен файлов которые разделены символами символов U + 005C REVERSE SOLIDUS().
Отчет об ошибке https://bugzilla.mozilla.org/show_bug.cgi?id=1311823
Отбрасывание файла в <textarea> при URI данных
Следующий комментарий Neal Deakin в отчете об ошибке
Я думаю, что упомянутые шаги:
- Откройте данные: text/html,
- Перетащите файл с рабочего стола на текстовое поле
Я могу воспроизвести это на Linux, но не на Windows или Mac.
Догадка выше правильная; Linux включает данные в виде URL-адреса и также открытый текст.
удаленные файлы в data:
prototcol data URI
в firefox, а хром, хром
data:text/html,<textarea></textarea>
Firefox
Полное имя пути к файлу или папке, установленному как .value
<textarea>
.
Chrome, хром
Отбрасывая файл в data URI
, имеющий только элемент textarea
в chrome, хром заменяет data URI
на удаленный путь файла в адресной строке и загружает выпавший файл на той же вкладке, заменяя data URI
содержимым отбрасываемого файла.
plnkr http://plnkr.co/edit/ZfAGEAiyLLq8rGXD2ShE?p=preview
html
, javascript
для воспроизведения описанной выше проблемы
<!DOCTYPE html>
<html>
<head>
<style>
body {
height: 400px;
}
textarea {
width: 95%;
height: inherit;
}
</style>
<script>
window.onload = function() {
var button = document.querySelector("#myfile + button");
var input = document.getElementById("myfile");
var display = document.getElementById("DisplayText");
var text = null;
function readFullPathToFileOnUserFileSystem(e) {
var path = e.target.value;
console.log(path);
var w = window.open(path, "_blank");
var img = new Image;
img.crossOrigin = "anonymous";
img.onload = function() {
document.body.appendChild(this);
}
img.onerror = function(err) {
console.log("img error", err.message)
}
img.src = path;
var request = new XMLHttpRequest();
request.open("GET", path.trim(), true);
request.onload = function() {
console.log(this.responseText)
}
request.error = function(err) {
console.log(err.message)
}
request.send();
}
display.addEventListener("input", readFullPathToFileOnUserFileSystem);
input.addEventListener("change", addDoc);
input.addEventListener("progress", function(event) {
console.log("progress", event)
});
button.addEventListener("click", handleText)
function addDoc(event) {
var mozResult = [];
function mozReadDirectories(entries, path) {
console.log("dir", entries, path);
return [].reduce.call(entries, function(promise, entry) {
return promise.then(function() {
console.log("entry", entry);
return Promise.resolve(entry.getFilesAndDirectories() || entry)
.then(function(dir) {
console.log("dir getFilesAndDirectories", dir)
return dir
})
})
}, Promise.resolve())
.catch(function(err) {
console.log(err, err.message)
})
.then(function(items) {
console.log("items", items);
var dir = items.filter(function(folder) {
return folder instanceof Directory
});
var files = items.filter(function(file) {
return file instanceof File
});
if (files.length) {
console.log("files:", files, path);
mozResult = mozResult.concat.apply(mozResult, files);
}
if (dir.length) {
console.log(dir, dir[0] instanceof Directory, dir[0]);
return mozReadDirectories(dir, dir[0].path || path);
} else {
if (!dir.length) {
return Promise.resolve(mozResult).then(function(complete) {
return complete
})
}
}
})
.catch(function(err) {
console.log(err)
})
};
console.log("files", event.target.files);
if ("getFilesAndDirectories" in event.target) {
return (event.type === "drop" ? event.dataTransfer : event.target)
.getFilesAndDirectories()
.then(function(dir) {
if (dir[0] instanceof Directory) {
console.log(dir)
return mozReadDirectories(dir, dir[0].path || path)
.then(function(complete) {
console.log("complete:", complete);
event.target.value = null;
});
} else {
if (dir[0] instanceof File && dir[0].size > 0) {
return Promise.resolve(dir)
.then(function(complete) {
console.log("complete:", complete);
})
} else {
if (dir[0].size == 0) {
throw new Error("could not process '" + dir[0].name + "' directory" + " at drop event at firefox, upload folders at 'Choose folder...' input");
}
}
}
}).catch(function(err) {
console.log(err)
})
}
var reader = new FileReader();
reader.onload = function(e) {
text = reader.result;
console.log("FileReader.result", text);
button.removeAttribute("disabled");
}
reader.onerror = function(err) {
console.log(err, err.loaded, err.loaded === 0, file);
button.removeAttribute("disabled");
}
reader.onprogress = function(e) {
console.log(e, e.lengthComputable, e.loaded, e.total);
}
reader.readAsArrayBuffer(file);
}
function handleText() {
// do stuff with `text`: `reader.result` from `addDoc`
display.textContent = text;
button.setAttribute("disabled", "disabled");
// set `text` to `null` if not needed or referenced again
text = null;
}
}
</script>
</head>
<body>
<input type="file" id="myfile" webkitdirectory directory allowdirs>
<button type="button" disabled>Add Document</button>
<br>
<br>
<textarea id="DisplayText"></textarea>
</body>
</html>
plnkr http://plnkr.co/edit/8Ovw3IlYKI8BYsLhzV88?p=preview
Вы можете использовать событие change
, присоединенное к элементу #myfile
, чтобы обрабатывать действие выбора файла пользователем.
Подставить элемент <textarea>
для элемента <p>
для отображения результата события load
из .readAsText()
.
Чтобы отобразить .result
из FileReader
в click
в элементе button
, установите переменную text
в reader.result
в load
событие FileReader
в click
событие в button
установить .textContent
элемента #DisplayText
к переменной, ссылающейся на ранее установленный reader.result
.
<!DOCTYPE html>
<html>
<style>
body {
height: 400px;
}
textarea {
width:95%;
height: inherit;
}
</style>
<head>
<script>
window.onload = function() {
var button = document.querySelector("#myfile + button");
var input = document.getElementById("myfile");
var display = document.getElementById("DisplayText");
var text = null;
input.addEventListener("change", addDoc);
button.addEventListener("click", handleText)
function addDoc(event) {
var file = this.files[0]
var reader = new FileReader();
reader.onload = function(e) {
text = reader.result;
button.removeAttribute("disabled");
}
reader.onerror = function(err) {
console.log(err, err.loaded
, err.loaded === 0
, file);
button.removeAttribute("disabled");
}
reader.readAsText(event.target.files[0]);
}
function handleText() {
// do stuff with `text`: `reader.result` from `addDoc`
display.textContent = text;
button.setAttribute("disabled", "disabled");
// set `text` to `null` if not needed or referenced again
text = null;
}
}
</script>
</head>
<body>
<input type="file" id="myfile" accept="text/*">
<button type="button" disabled>Add Document</button><br><br>
<textarea id="DisplayText"></textarea>
</body>
</html>