6

Ce que j'essaie d'accomplir est de télécharger des données binaires, en particulier un ByteArray représentant une image PNG, vers un serveur utilisant la classe URLLoader en conjonction avec URLRequest.Exception de sécurité Flash inattendue lors de l'utilisation de URLLoader

Lorsque j'ai défini la propriété contentType de l'URLRequest sur 'multipart/form-data' au lieu de la valeur par défaut, l'appel à urlLoader.load() entraîne une exception de sécurité.

Lorsque je laisse la propriété contentType par défaut, cela fonctionne correctement, mais prend beaucoup de temps (proportionnellement à la longueur du fichier PNG) pour télécharger le fichier sur le serveur. Donc, ma question est pourquoi est-ce que je reçois cette exception de sécurité? Et comment puis-je l'éviter?

Notez que mon SWF est servi à partir d'un serveur de développement, pas du système de fichiers local (le serveur de développement Google App Engine pour être précis).

Voici le code:

var pngFile:ByteArray = PNGEncoder.encode(bitmapData); 

var urlRequest:URLRequest = new URLRequest('/API/uploadImage'); 

// With this line of code, the call to urlLoader.load() throws the following security exception: 
// 'SecurityError: Error #2176: Certain actions, such as those that display a pop-up window, may only be invoked upon user interaction, for example by a mouse click or button press.' 
urlRequest.contentType = 'multipart/form-data'; 

urlRequest.method = URLRequestMethod.POST; 
urlRequest.data = pngFile; 
urlRequest.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache')); 

urlLoader = new URLLoader(); 
urlLoader.dataFormat = URLLoaderDataFormat.TEXT; 
urlLoader.addEventListener(Event.COMPLETE, onUploadComplete); 
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, onUploadError); 

NextFrame.addCallback(function() { 
    urlLoader.load(urlRequest); 
}); 

Répondre

13

Il pourrait être possible que contentType ne se réfère pas à ce que les données que vous envoyez, mais à ce que les données que vous recevez. Essayez de régler le requestHeaders, qui devrait fonctionner:

urlRequest.requestHeaders.push(new URLRequestHeader('Content-type', 'multipart/form-data')); 

Aussi, j'ai trouvé un morceau de code où dans l'un de mes projets. Le code fonctionne et envoie des données JPEG binaires au serveur, en utilisant POST. Je l'ai dit il y a quelque temps et je ne peux pas expliquer pourquoi j'ai fait les choses de cette façon, mais peut-être que ça aide. Je le coller comme est:

function sendData(submitPath:String, descriere:String):void { 
    // building the url request for uploading the jpeg to the server 
    var header:URLRequestHeader = new URLRequestHeader('Content-type', 'application/octet-stream'); 
    var jpgURLRequest:URLRequest = new URLRequest(submitPath+'/id/'+player.id+'/path/'+player.contentPath.replace('/','')+'/width/'+player.videoWidth+'/height/'+player.videoHeight+'/descriere/'+descriere+'/timp/'+time); 
    jpgURLRequest.requestHeaders.push(header); 
    jpgURLRequest.method = URLRequestMethod.POST; 
    jpgURLRequest.data = screenShot; 

    // sending the data to the server 
    var sender:URLLoader = new URLLoader(); 
    sender.load(jpgURLRequest); 
} 
+1

Merci beaucoup! J'ai été perplexe pendant des heures la nuit dernière ... J'ai dû modifier quelques trucs, alors vois ma réponse pour exactement comment ça a fini par fonctionner – Cameron

+0

De rien. Oui, bon à savoir sur la frontière. Cordialement. – evilpenguin

+0

je vous remercie beaucoup ... je fais rarement flash dev, mais j'avais besoin de mettre à jour un uploader, et cela m'a finalement sauvé :) – will

8

Juste pour être complet, voici comment j'ai fini par mettre en place mon objet URLRequest (tout est resté bien le même):

urlRequest.method = URLRequestMethod.POST; 
urlRequest.data = UploadPostHelper.getPostData('filename', pngFile); 
urlRequest.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache')); 
urlRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary())); 

La clé, comme l'a fait remarquer evilpenguin, il ne s'agissait pas de définir la propriété contentType, mais de la mettre dans l'en-tête. En utilisant simplement 'multipart/form-data', j'ai rencontré une erreur du côté serveur concernant les limites POST non valides. J'ai donc utilisé a class called UploadPostHelper pour créer une limite valide et un corps POST pour les téléchargements de fichiers.

Cela a corrigé l'erreur de sécurité mystérieuse (je ne sais toujours pas pourquoi cela est arrivé), et les très longues attentes pour les téléchargements.

Il est à noter que l'exemple de code pour l'utilisation de UploadPostHelper implique la définition de la propriété contentType de l'objet URLRequest, et cela fonctionne apparemment pour certaines personnes, mais pas dans mon cas.

4

J'ai eu le même problème. Cela a bien fonctionné lors de la soumission à un script PHP, mais pas à un script ASP. Après avoir déplacé le type de contenu vers un requestHeader, cela fonctionne correctement. Voici mon code:

// Object containing form fields 
var formdata = new Object(); 
formdata.Email = textArray[8].text; 

//URLRequest containing the form fields and the attached image 
var urlRequest : URLRequest = new URLRequest(url); 
urlRequest.method = URLRequestMethod.POST; 
urlRequest.data = UploadPostHelper.getPostData(imageName, imageByteArray, formdata); 
urlRequest.requestHeaders.push(new URLRequestHeader('Cache-Control', 'no-cache')); 
urlRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'multipart/form-data; boundary=' + UploadPostHelper.getBoundary())); 

//URLLoader to load the request 
var urlLoader : URLLoader = new URLLoader(); 
urlLoader.dataFormat = URLLoaderDataFormat.BINARY; 
urlLoader.load(urlRequest); 
Questions connexes