Wie kann ich abrufen $_FILES
in PHP, wenn ich über einen Web Worker hochlade? Als ich versuchte zu benutzen FormData
bekam ich folgenden Fehler:
Fehler: FormData ist nicht definiert
Das ist mein Code:
function uploadFile(blobFile, fileName, filePart, totalChunks) {
//if I try to put this
//var formData = new FormData(); //it does not work
var xhr = new XMLHttpRequest();
xhr.open("POST", "upload.php"+"?"+"file="+fileName + filePart, true);
xhr.onload = function(e) {};
xhr.send(blobFile);
}
Also in upload.php, wie soll ich den tmp-Pfad bekommen? $_FILES
? Für alle Fälle zeige ich auch die Seite, die auf den Webworker verweist:
<form id="fileuploader" enctype="multipart/form-data" method="post" action="upload.php">
<label for="fileToUpload">Select Files to Upload</label><br />
<input type="file" name="fileToUpload[]" multiple="" id="fileToUpload" onchange="fileList();"/><br />
<input type="button" onclick="sendRequest();" value="Upload" />
<!-- a place for File Listing -->
<div id="fileList"></div>
</form>
<script type="text/javascript">
function sendRequest() {
var worker = new Worker("fileupload.js");
worker.onmessage = function(e) {
alert(e.data);
}
var file = document.getElementById('fileToUpload');
for(var i = 0; i < file.files.length; i++) {
worker.postMessage(file.files[i]);
}
}
Ich habe das folgende Polyfill geschrieben, um das zu emulieren FormData
Methode in Web Workers. Da Webworker DOM nicht unterstützen, wird die new FormData(<HTMLFormElement>);
Konstruktoraufruf wird ebenfalls nicht unterstützt.
File
und Blob
Objekte, typisierte Arrays und Strings werden jedoch vom Polyfill unterstützt.
Es wurde ursprünglich als Teil der Antwort auf das Hochladen einer Datei in einer Google Chrome-Erweiterung gepostet. Um ein Beispiel zu sehen, wie es verwendet werden kann, werfen Sie einen Blick auf die andere Antwort.
/*
* FormData for XMLHttpRequest 2 - Polyfill for Web Worker (c) 2012 Rob W
* License: Creative Commons BY - http://creativecommons.org/licenses/by/3.0/
* - append(name, value[, filename])
* - toString: Returns an ArrayBuffer object
*
* Specification: http://www.w3.org/TR/XMLHttpRequest/#formdata
* http://www.w3.org/TR/XMLHttpRequest/#the-send-method
* The .append() implementation also accepts Uint8Array and ArrayBuffer objects
* Web Workers do not natively support FormData:
* http://dev.w3.org/html5/workers/#apis-available-to-workers
**/
(function() {
// Export variable to the global scope
(this == undefined ? self : this)['FormData'] = FormData;
var ___send$rw = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype['send'] = function(data) {
if (data instanceof FormData) {
if (!data.__endedMultipart) data.__append('--' + data.boundary + '--\r\n');
data.__endedMultipart = true;
this.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + data.boundary);
data = new Uint8Array(data.data).buffer;
}
// Invoke original XHR.send
return ___send$rw.call(this, data);
};
function FormData() {
// Force a Constructor
if (!(this instanceof FormData)) return new FormData();
// Generate a random boundary - This must be unique with respect to the form's contents.
this.boundary = '------RWWorkerFormDataBoundary' + Math.random().toString(36);
var internal_data = this.data = [];
/**
* Internal method.
* @param inp String | ArrayBuffer | Uint8Array Input
*/
this.__append = function(inp) {
var i=0, len;
if (typeof inp === 'string') {
for (len=inp.length; i<len; i++)
internal_data.push(inp.charCodeAt(i) & 0xff);
} else if (inp && inp.byteLength) {/*If ArrayBuffer or typed array */
if (!('byteOffset' in inp)) /* If ArrayBuffer, wrap in view */
inp = new Uint8Array(inp);
for (len=inp.byteLength; i<len; i++)
internal_data.push(inp[i] & 0xff);
}
};
}
/**
* @param name String Key name
* @param value String|Blob|File|Uint8Array|ArrayBuffer Value
* @param filename String Optional File name (when value is not a string).
**/
FormData.prototype['append'] = function(name, value, filename) {
if (this.__endedMultipart) {
// Truncate the closing boundary
this.data.length -= this.boundary.length + 6;
this.__endedMultipart = false;
}
var valueType = Object.prototype.toString.call(value),
part="--" + this.boundary + '\r\n' +
'Content-Disposition: form-data; name="' + name + '"';
if (/^\[object (?:Blob|File)(?:Constructor)?\]$/.test(valueType)) {
return this.append(name,
new Uint8Array(new FileReaderSync().readAsArrayBuffer(value)),
filename || value.name);
} else if (/^\[object (?:Uint8Array|ArrayBuffer)(?:Constructor)?\]$/.test(valueType)) {
part += '; filename="'+ (filename || 'blob').replace(/"/g,'%22') +'"\r\n';
part += 'Content-Type: application/octet-stream\r\n\r\n';
this.__append(part);
this.__append(value);
part="\r\n";
} else {
part += '\r\n\r\n' + value + '\r\n';
}
this.__append(part);
};
})();
Das formData-Objekt benötigt Zugriff auf das DOM, um das Formular abzurufen, und Webworker haben keinen Zugriff auf das DOM, sodass diese beiden nicht zusammenarbeiten. Das ist nicht wirklich das, wofür Webworker gedacht sind.
– adeneo
14. Dezember 2012 um 0:34 Uhr
@adeneo, du meinst also, es gibt keine Möglichkeit, das zum Laufen zu bringen? Gibt es eine andere Möglichkeit ohne Formdata? weil basierend auf diesem Artikel Webworker zum Hochladen von Dateien verwendet werden soll kongaraju.blogspot.com/2012/07/… scheint ein guter zu sein, aber er zeigt den Serverteil nicht
– Hirsche
14. Dezember 2012 um 0:38 Uhr
Ich bin mir nicht sicher, ich weiß nur, dass ein Webworker niemals Zugriff auf das DOM haben kann und FormData ein Objekt ziemlich basierend auf einem Formular erstellt, und ohne Zugriff auf das DOM wäre es schwierig, FormData so zum Laufen zu bringen, wie es funktioniert. überhaupt keinen Zugriff auf das Formular haben.
– adeneo
14. Dezember 2012 um 0:46 Uhr
@adeneo Das OP versucht nicht, die zu verwenden
<form>
Objekt (das ist nicht möglich). Stattdessen postet erFile
Objekte, die aufgrund der richtig empfangen werden strukturierter Klonalgorithmus. Wie ich unten demonstriere, bedeutet das Fehlen von DOM nicht, dass dieFormData
API kann nicht verwendet werden – siehe Antwort unten.– Rob W
20. Dezember 2012 um 10:36 Uhr