Uploadify跨域上传原理

2023-10-17 21:20
文章标签 原理 上传 跨域 uploadify

本文主要是介绍Uploadify跨域上传原理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引用:http://www.cnblogs.com/me-sa/archive/2010/05/21/How-Uploadify-Cross-Domain.html

《 回头再说:jQuery跨域原理 》一文提到浏览器的同源策略以及使用JsonP的方式实现跨域;在评论中金色海洋提出了一个问题:

我最近在用 uploadify + ashx 来做文件上传的功能。都测试成功了,但是发现我可以提交到其他的网站里面。

我是在本地测试了。两个网站,IP地址相同,使用端口来区分。

一个端口是8001,另一个是8002 。

两个网站都有上传文件的程序,我发现,如果我把8001端口的站点的

'script': '/_CommonPage/UploadHandler.ashx',

改成

'script': 'http://192.168.0.1:8002/_CommonPage/UploadHandler.ashx',

居然也能够成功上传文件,传到了8002对应的网站里面。

我不知道如果换成域名了,是否也是可以往不同的域名里上传文件?

如果是的话,是不是很危险?如何来验证呢? 

 我给出的错误解释

         看到金色海洋的问题之后,我下载下来Uploadify源码看了一下,然后非常草率的给出了一个解释,点击这里;对于这个错误的解释,园友mx1700提出了质疑;于是下班回家之后,我开始动手模拟金色海洋的环境,试图一探究竟; 

Uploadify工作机制

       我在VS2010里面新建了一个webApplication,在页面上使用Uploadify,页面代码如下:   

 1 <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
 2     <script src="Scripts/jquery.uploadify.v2.1.0.js" type="text/javascript"></script>
 3     <script src="Scripts/swfobject.js" type="text/javascript"></script>
 4     <script type="text/javascript">
 5        // <![CDATA[
 6         var id = "55";
 7         var theString = "asdf";
 8         $(document).ready(function () {
 9             $('#fileInput').uploadify({
10                 'uploader': 'uploadify.swf',
11                 'script': 'http://www.b.com:84/Uploader.ashx',
12                 'scriptData': { 'id': id, 'foo': theString },
13                 'cancelImg': 'cancel.png',
14                 'auto': true,
15                 'multi': true,
16                 'fileDesc': 'Image Files',
17                 'fileExt': '*.jpg;*.png;*.gif;*.bmp;*.jpeg',
18                 'queueSizeLimit': 90,
19                 'sizeLimit': 4000000,
20                 'buttonText': 'Choose Images',
21                 'folder': '/uploads',
22                 'onAllComplete': function (event, queueID, fileObj, response, data) {
23 
24                 }
25             });
26         });
27    // ]]></script>
28 
29    <input id="fileInput" name="fileInput" type="file" />
View Code

通过单步调试,我发现页面上会通过swfobject.js动态加载一个Flash,我们在页面上操作的实际上是Flash.  jQuery的作用是页面、Flash、目标服务器之间的黏合剂。它定义用户上传操作在不同时机的响应函数.而在这里 我所认为“发送数据上传文件”的函数,只不过是一个用来检查服务器上是不是已经存在同名文件的函数;由于这个检查有可能是跨域,所以 Uploadify间接使用了jQuery的JsonP跨域解决方案.

 

        通过排除,我们能有一个基本的判断:文件上传是在Flash里面完成的.那么Flash里面做了什么呢?还好有uploadify.fla文件,使用Flex Builder打开这个文件来看,果然如此,很多朋友没有Flex Builde,这里贴出完整代码;可以看到,

1
// Upload each file<br>function uploadFile(file:FileReference, index:int, ID:String, single:Boolean):

    实际的上传操作,而上传不同时机使用的很多函数都是定义在jquery.uploadify.v2.1.0.min.js文件里面.

  1 uploadify.fla
  2 /*
  3 Uploadify v2.1.0
  4 Release Date: August 24, 2009
  5 
  6 Copyright (c) 2009 Ronnie Garcia, Travis Nickels
  7 
  8 Permission is hereby granted, free of charge, to any person obtaining a copy
  9 of this software and associated documentation files (the "Software"), to deal
 10 in the Software without restriction, including without limitation the rights
 11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12 copies of the Software, and to permit persons to whom the Software is
 13 furnished to do so, subject to the following conditions:
 14 
 15 The above copyright notice and this permission notice shall be included in
 16 all copies or substantial portions of the Software.
 17 
 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24 THE SOFTWARE.
 25  */
 26 
 27 import flash.external.ExternalInterface;
 28 import flash.net.*;
 29 import flash.events.*;
 30 import flash.display.*;
 31 import com.adobe.serialization.json.JSON;
 32 
 33  // Align the stage to the top left and don't scale it
 34  stage.align = StageAlign.TOP_LEFT;
 35 stage.scaleMode = StageScaleMode.NO_SCALE;
 36 
 37  // Create all the variables
 38  var param:Object = LoaderInfo(this.root.loaderInfo).parameters;
 39  var fileRefSingle:FileReference    = new FileReference();
 40  var fileRefMulti:FileReferenceList = new FileReferenceList();
 41  var fileRefListener:Object = new Object();
 42  var fileQueue:Array        = new Array();
 43  var fileItem:Object        = new Object();
 44  var activeUploads:Object   = new Object();
 45  var errorArray:Array       = new Array();
 46  var counter:Number        = 0;
 47  var filesSelected:Number  = 0;
 48  var filesReplaced:Number  = 0;
 49  var filesUploaded:Number  = 0;
 50  var filesChecked:Number   = 0;
 51  var errors:Number         = 0;
 52  var kbs:Number            = 0;
 53 var allBytesLoaded:Number = 0;
 54 var allBytesTotal:Number  = 0;
 55 var allKbsAvg:Number      = 0;
 56 var allowedTypes:Array;
 57 var scriptURL:URLRequest;
 58 var variables:URLVariables;
 59 var queueReversed:Boolean = false;
 60 
 61 // For debugging, alert any value to javascript
 62 function debug(someValue) {
 63     ExternalInterface.call('alert("' + someValue + '")');
 64 }
 65 
 66 // Trigger a javascript event
 67 function $trigger(eventName:String, ... args):void {
 68     // Add parenthesis
 69     function p(s:String):String {
 70         return ('('+s+')');
 71     }
 72     // Add quotes
 73     function q(s:String):String {
 74         return ('"'+s+'"');
 75     }
 76     var list:Array = [q(eventName)]; //Add the event to the array
 77     if (args.length > 0) list.push(JSON.encode(args)); // Add arguments to the array as a JSON object
 78     ExternalInterface.call(['jQuery'+p(q('#'+param.uploadifyID)), p(list.join(','))].join('.trigger')); // Trigger the event
 79 }
 80 
 81 // Random string generator for queue IDs
 82 function generateID(len:Number):String {
 83     var chars:Array = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
 84     var ID:String = '';
 85     var index:Number;
 86     for (var n:int = 0; n < len; n++) {
 87         ID += chars[Math.floor(Math.random() * 25)];
 88     }
 89     return ID;
 90 }
 91 
 92 // Load the button image
 93 function setButtonImg():void {
 94     if (param.buttonImg) {
 95         var btnLoader:Loader    = new Loader();
 96         var btnImage:URLRequest = new URLRequest(param.buttonImg);
 97         browseBtn.addChild(btnLoader);
 98         btnLoader.load(btnImage);
 99     }
100     if (!param.hideButton && !param.buttonImg) {
101         browseBtn.empty.alpha = 1;
102     }
103 }
104 setButtonImg();
105 
106 // Hide or show the button
107 function hideButton(hideValue:Boolean):void {
108     if (hideValue) {
109         browseBtn.empty.alpha = 0;
110     } else {
111         browseBtn.empty.alpha = 1;
112     }
113 }
114 
115 // Set the text on the button
116 function setButtonText():void {
117     if (param.buttonText) {
118         browseBtn.empty.buttonText.text = unescape(param.buttonText);
119     }
120 }
121 setButtonText();
122 
123 // This is important for clicking the button correctly
124 browseBtn.buttonMode = true;
125 browseBtn.useHandCursor = true;
126 browseBtn.mouseChildren = false;
127 
128 // Set the size of the button
129 function setButtonSize():void {
130     if (param.hideButton) {
131         browseBtn.width  = param.width;
132         browseBtn.height = param.height;
133     }
134     // Set the size of the button on the page
135     ExternalInterface.call('jQuery("#' + param.uploadifyID + '").attr("width",' + param.width + ')');
136     ExternalInterface.call('jQuery("#' + param.uploadifyID + '").attr("height",' + param.height + ')');
137 }
138 setButtonSize();
139 
140 // Setup the rollover animation
141 if (param.rollover) {
142     browseBtn.addEventListener(MouseEvent.ROLL_OVER, function (event:MouseEvent):void {
143         event.currentTarget.y = -param.height;
144     });
145     browseBtn.addEventListener(MouseEvent.ROLL_OUT, function (event:MouseEvent):void {
146         event.currentTarget.y = 0;
147     });
148     browseBtn.addEventListener(MouseEvent.MOUSE_DOWN, function (event:MouseEvent):void {
149         event.currentTarget.y = -(param.height * 2);
150     });
151 }
152 
153 // create the scriptData variable if it doesn't exist
154 if (!param.scriptData) {
155     param.scriptData = '';
156 }
157 
158 // Limit the file types
159 function setAllowedTypes():void {
160     allowedTypes = [];
161     if (param.fileDesc && param.fileExt) {
162         var fileDescs:Array = param.fileDesc.split('|');
163         var fileExts:Array = param.fileExt.split('|');
164         for (var n = 0; n < fileDescs.length; n++) {
165             allowedTypes.push(new FileFilter(fileDescs[n], fileExts[n]));
166         }
167     }
168 }
169 setAllowedTypes();
170 
171 // Set or get the variables
172 function uploadify_updateSettings(settingName:String, settingValue) {
173     if(settingValue == null) {
174         if (settingName == 'queueSize') {
175             return fileQueue.length;
176         }
177         return param[settingName];
178     } else {
179         param[settingName] = settingValue;
180         if(settingName == 'buttonImg') setButtonImg();
181         if(settingName == 'buttonText') setButtonText();
182         if(settingName == 'fileDesc' || settingName == 'fileExt') setAllowedTypes();
183         if(settingName == 'width' || settingName == 'height') setButtonSize();
184         if(settingName == 'hideButton') hideButton(settingValue);
185         return true;
186     }
187 }
188 
189 // Browse for Files
190 browseBtn.addEventListener(MouseEvent.CLICK, function():void {
191     if (objSize(activeUploads) == 0) { // Don't browse if it's uploading
192         if (!allowedTypes) {
193             (!param.multi) ? fileRefSingle.browse() : fileRefMulti.browse();
194         } else {
195             (!param.multi) ? fileRefSingle.browse(allowedTypes) : fileRefMulti.browse(allowedTypes);
196         }
197     }
198 });
199 
200 // Get the size of an object
201 function objSize(obj:Object):Number {
202     var i:int = 0;
203     for (var item in obj) {
204         i++;
205     }
206     return i;
207 }
208 
209 // Get actual folder path
210 function getFolderPath():String {
211     var folder:String = param.folder;
212     if (param.folder.substr(0,1) != '/' && param.folder.substr(0,4) != 'http') {
213         folder = param.pagepath + param.folder;
214         var folderParts:Array = folder.split('/');
215         for (var i = 0; i < folderParts.length; i++) {
216             if (folderParts[i] == '..') {
217                 folderParts.splice(i - 1, 2);
218             }
219         }
220         folder = folderParts.join('/');
221     }
222     return folder;
223 }
224 
225 // Get the array index of the item in the fileQueue
226 function getIndex(ID:String):Number {
227     var index:int;
228     for (var n:Number = 0; n < fileQueue.length; n++) {
229         if (fileQueue[n].ID == ID) {
230             index = n;
231         }
232     }
233     return index;
234 }
235 
236 // Check if a file with the same name is already in the queue
237 function inQueue(fileName:String):Object {
238     var obj:Object = new Object();
239     obj.testResult = false;
240     if (fileQueue.length > 0) {
241         for (var n = 0; n < fileQueue.length; n++) {
242             if (fileQueue[n].file.name == fileName) {
243                 obj.size       = fileQueue[n].file.size;
244                 obj.ID         = fileQueue[n].ID;
245                 obj.arrIndex   = n;
246                 obj.testResult = true;
247             }
248         }
249     }
250     return obj;
251 }
252 
253 // When selecting a file
254 function fileSelectSingleHandler(event:Event):void {
255     // Check if the filename already exists in the queue
256     fileItem = new Object();
257     fileItem.file = FileReference(event.target);
258     uploadify_clearFileUploadQueue(true);
259     var ID:String = generateID(6);
260     fileItem.ID = ID;
261     fileQueue.push(fileItem);
262     filesSelected = 1;
263     allBytesTotal = fileItem.file.size;
264     $trigger('uploadifySelect',ID,fileItem.file);
265     $trigger('uploadifySelectOnce',{
266         'fileCount'     : fileQueue.length,
267         'filesSelected' : filesSelected,
268         'filesReplaced' : filesReplaced,
269         'allBytesTotal' : allBytesTotal
270     });
271     filesSelected = 0;
272     filesReplaced = 0;
273     if (param.auto) {
274         if (param.checkScript) { 
275             uploadify_uploadFiles(null, false);
276         } else {
277             uploadify_uploadFiles(null, true);
278         }
279     }
280 }
281 
282 function fileSelectMultiHandler(event:Event):void {
283     var ID:String = '';
284     for (var n:Number = 0; n < fileRefMulti.fileList.length; n++) {
285         fileItem = new Object();
286         fileItem.file = fileRefMulti.fileList[n];
287         // Check if the filename already exists in the queue
288         var queueTest:Object = inQueue(fileRefMulti.fileList[n].name);
289         if (queueTest.testResult) {
290             allBytesTotal -= queueTest.size;
291             allBytesTotal += fileItem.file.size;
292             fileItem.ID    = fileQueue[queueTest.arrIndex].ID;
293             fileQueue[queueTest.arrIndex] = fileItem;
294             filesReplaced++;
295         } else {
296             if (fileQueue.length < param.queueSizeLimit) {
297                 ID = generateID(6);
298                 fileItem.ID = ID;
299                 fileQueue.push(fileItem);
300                 filesSelected++;
301                 allBytesTotal += fileItem.file.size;
302                 $trigger('uploadifySelect',ID,fileItem.file);
303             } else {
304                 $trigger('uploadifyQueueFull',param.queueSizeLimit);
305                 break;
306             }
307         }
308     }
309     $trigger('uploadifySelectOnce',{
310         'fileCount'     : fileQueue.length,
311         'filesSelected' : filesSelected,
312         'filesReplaced' : filesReplaced,
313         'allBytesTotal' : allBytesTotal
314     });
315     filesSelected = 0;
316     filesReplaced = 0;
317     if (param.auto) {
318         if (param.checkScript) { 
319             uploadify_uploadFiles(null, false);
320         } else {
321             uploadify_uploadFiles(null, true);
322         }
323     }
324 }
325 fileRefSingle.addEventListener(Event.SELECT, fileSelectSingleHandler);
326 fileRefMulti.addEventListener(Event.SELECT, fileSelectMultiHandler);
327 
328 // This function should run during upload so flash doesn't timeout
329 function uploadCounter(event:Event):void {
330     counter++;
331 }
332 
333 // Start the upload
334 function uploadify_uploadFiles(ID:String, checkComplete:Boolean):void {
335     if (!queueReversed) {
336         fileQueue.reverse();
337         queueReversed = true;
338     }
339     if (param.script.substr(0,1) != '/' && param.script.substr(0,4) != 'http') param.script = param.pagepath + param.script;
340     scriptURL = new URLRequest(param.script);
341     variables = new URLVariables();
342     (param.method.toUpperCase() == "GET") ? scriptURL.method = URLRequestMethod.GET : scriptURL.method = URLRequestMethod.POST;
343     if (param.scriptData != '') variables.decode(unescape(param.scriptData));
344     if (param.fileExt) variables.fileext = unescape(param.fileExt);
345     variables.folder = unescape(getFolderPath());
346     scriptURL.data = variables;
347     if (param.checkScript && !checkComplete) {
348         var fileQueueObj:Object = new Object();
349         if (ID) {
350             var index:int = getIndex(ID);
351             if (fileQueue[index].file) {
352                 fileQueueObj[fileQueue[index].ID] = fileQueue[index].file.name;
353             }
354             $trigger('uploadifyCheckExist',param.checkScript,fileQueueObj,param.folder,true);
355         } else {
356             for (var n:Number = fileQueue.length - 1; n > -1; n--) {
357                 if (fileQueue[n]) {
358                     fileQueueObj[fileQueue[n].ID] = fileQueue[n].file.name;
359                 }
360             }
361             $trigger('uploadifyCheckExist',param.checkScript,fileQueueObj,param.folder,false);
362         }
363     } else {
364         if (ID && fileQueue[getIndex(ID)].file) {
365             uploadFile(fileQueue[getIndex(ID)].file, getIndex(ID), ID, true);
366         } else {
367             for (n = fileQueue.length - 1; n > -1; n--) {
368                 if (objSize(activeUploads) < parseInt(param.simUploadLimit)) {
369                     if (!activeUploads[fileQueue[n].ID] && fileQueue[n].file) {
370                         uploadFile(fileQueue[n].file, n, fileQueue[n].ID, false);
371                     }
372                 } else {
373                     break;
374                 }
375             }
376         }
377     }
378 }
379 
380 function queueIsNotEmpty(item:*, index:int, array:Array):Boolean {
381     return (item.file != '');
382 }
383 
384 // Upload each file
385 function uploadFile(file:FileReference, index:int, ID:String, single:Boolean):void {
386     var startTimer:Number      = 0;
387     var lastBytesLoaded:Number = 0;
388     var kbsAvg:Number          = 0;
389     
390     function fileOpenHandler(event:Event) {
391         startTimer = getTimer();
392         $trigger('uploadifyOpen',ID,event.currentTarget);
393     }
394     
395     function fileProgressHandler(event:ProgressEvent):void {
396         var percentage:Number = Math.round((event.bytesLoaded / event.bytesTotal) * 100);
397         if ((getTimer()-startTimer) >= 150) {
398             kbs = ((event.bytesLoaded - lastBytesLoaded)/1024)/((getTimer()-startTimer)/1000);
399             kbs = int(kbs*10)/10; 
400             startTimer = getTimer();
401             if (kbsAvg > 0) {
402                 kbsAvg = (kbsAvg + kbs)/2;
403             } else {
404                 kbsAvg = kbs;
405             }
406             allKbsAvg = (allKbsAvg + kbsAvg)/2;
407         }
408         allBytesLoaded += (event.bytesLoaded - lastBytesLoaded);
409         lastBytesLoaded = event.bytesLoaded;
410         $trigger('uploadifyProgress',ID,event.currentTarget,{
411             'percentage'     : percentage,
412             'bytesLoaded'    : event.bytesLoaded,
413             'allBytesLoaded' : allBytesLoaded,
414             'speed'          : kbs
415         });
416     }
417     
418     function fileCompleteHandler(event:DataEvent):void {
419         if (kbsAvg == 0) {
420             kbs = (file.size/1024)/((getTimer()-startTimer)/1000);
421             kbsAvg = kbs;
422             allKbsAvg = (allKbsAvg + kbsAvg)/2;
423         }
424         
425         allBytesLoaded -= lastBytesLoaded;
426         allBytesLoaded += event.currentTarget.size;
427         
428         $trigger('uploadifyProgress',ID,event.currentTarget,{
429             'percentage'     : 100,
430             'bytesLoaded'    : event.currentTarget.size,
431             'allBytesLoaded' : allBytesLoaded,
432             'speed'          : kbs
433         });
434         $trigger('uploadifyComplete',ID,{
435                 'name'             : event.currentTarget.name,
436                 'filePath'         : getFolderPath() + '/' + event.currentTarget.name,
437                 'size'             : event.currentTarget.size,
438                 'creationDate'     : event.currentTarget.creationDate,
439                 'modificationDate' : event.currentTarget.modificationDate,
440                 'type'             : event.currentTarget.type
441             },
442             escape(event.data),{
443             'fileCount' : (fileQueue.length-1),
444             'speed'     : kbsAvg
445         });
446         filesUploaded++;
447         fileQueue.splice(getIndex(ID),1);
448         delete activeUploads[ID];
449         if (!single) {
450             uploadify_uploadFiles(null, true);
451         }
452         event.currentTarget.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, fileCompleteHandler);
453         if (!fileQueue.some(queueIsNotEmpty) && objSize(activeUploads) == 0) {
454             $trigger('uploadifyAllComplete',{
455                 'filesUploaded'  : filesUploaded,
456                 'errors'         : errors,
457                 'allBytesLoaded' : allBytesLoaded,
458                 'speed'          : allKbsAvg
459             });
460             resetVars();
461         }
462     }
463     
464     // Add all the event listeners
465     file.addEventListener(Event.OPEN, fileOpenHandler);
466     file.addEventListener(ProgressEvent.PROGRESS, fileProgressHandler);
467     file.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, fileCompleteHandler);
468     
469     // Reset all the numbers
470     function resetVars() {
471         filesUploaded  = 0;
472         errors         = 0;
473         allBytesLoaded = 0;
474         allBytesTotal  = 0;
475         allKbsAvg      = 0;
476         filesChecked   = 0;
477         queueReversed  = false;
478     }
479     
480     // Handle all the errors
481     file.addEventListener(HTTPStatusEvent.HTTP_STATUS, function(event:HTTPStatusEvent):void {
482         if (errorArray.indexOf(ID) == -1) {  
483             $trigger('uploadifyError',ID,event.currentTarget,{
484                 'type' : 'HTTP',
485                 'info' : event.status
486             });
487             finishErrorHandler(ID);
488         }
489     });
490     file.addEventListener(IOErrorEvent.IO_ERROR, function(event:IOErrorEvent):void {
491         if (errorArray.indexOf(ID) == -1) {
492             $trigger('uploadifyError',ID,event.currentTarget,{
493                 'type' : 'IO',
494                 'info' : event.text
495             });
496             finishErrorHandler(ID);
497         }
498     });
499     file.addEventListener(SecurityErrorEvent.SECURITY_ERROR, function(event:SecurityErrorEvent):void {
500         if (errorArray.indexOf(ID) == -1) { 
501             $trigger('uploadifyError',ID,event.currentTarget,{
502                 'type' : 'Security',
503                 'info' : event.text
504             });
505             finishErrorHandler(ID);
506         }
507     });
508     
509     // Common routines used by all errors
510     function finishErrorHandler(ID:String) {
511         errorArray.push(ID);
512         fileQueue[getIndex(ID)].file = '';
513         delete activeUploads[ID];
514         if (!single) {
515             uploadify_uploadFiles(null, true);
516         }
517         errors++;
518         if (!fileQueue.some(queueIsNotEmpty)) {
519             if (root.hasEventListener(Event.ENTER_FRAME)) {
520                 root.removeEventListener(Event.ENTER_FRAME, uploadCounter);
521             }
522             $trigger('uploadifyAllComplete',{
523                 'filesUploaded'  : filesUploaded,
524                 'errors'         : errors,
525                 'allBytesLoaded' : allBytesLoaded,
526                 'speed'          : allKbsAvg
527             });    
528             resetVars();
529         }
530     }
531     
532     if (param.sizeLimit && file.size > parseInt(param.sizeLimit)) {
533         if (errorArray.indexOf(ID) == -1) { 
534             $trigger('uploadifyError',ID,file,{
535                 'type' : 'File Size',
536                 'info' : param.sizeLimit
537             });
538             finishErrorHandler(ID);
539         }
540     } else {
541         file.upload(scriptURL, param.fileDataName);
542         activeUploads[ID] = true;
543     }
544 }
545 
546 function uploadify_cancelFileUpload(ID:String, single:Boolean, clearFast:Boolean):void {
547     var index:int = getIndex(ID);
548     var fileObj:Object = new Object();
549     if (fileQueue[index].file) {
550         fileObj = fileQueue[index].file;
551         fileQueue[index].file.cancel();
552         allBytesTotal -= fileQueue[index].file.size;
553     }
554 
555     fileQueue.splice(index,1);
556 
557     if (activeUploads[ID]) {
558         delete activeUploads[ID];
559         uploadify_uploadFiles(null, true);
560         if (root.hasEventListener(Event.ENTER_FRAME) && objSize(activeUploads) == 0) {
561             root.removeEventListener(Event.ENTER_FRAME, uploadCounter);
562         }
563     }
564 
565     $trigger('uploadifyCancel',ID,fileObj,{
566         'fileCount'     : (fileQueue.length),
567         'allBytesTotal' : allBytesTotal
568     },clearFast);
569 }
570 
571 // Cancel all uploads
572 function uploadify_clearFileUploadQueue(clearFast:Boolean):void {
573     if (!queueReversed) {
574         fileQueue.reverse();
575         queueReversed = true;
576     }
577     for (var n:Number = fileQueue.length - 1; n >= 0; n--) {
578         uploadify_cancelFileUpload(fileQueue[n].ID, false, clearFast);
579     }
580     if (root.hasEventListener(Event.ENTER_FRAME)) {
581         root.removeEventListener(Event.ENTER_FRAME, uploadCounter);
582     }
583     $trigger('uploadifyClearQueue');
584     filesUploaded  = 0;
585     errors         = 0;
586     allBytesLoaded = 0;
587     allBytesTotal  = 0;
588     allKbsAvg      = 0;
589     filesChecked   = 0;
590     queueReversed  = false;
591 }
592 
593 // Create all the callbacks for the functions
594 ExternalInterface.addCallback('updateSettings', uploadify_updateSettings);
595 ExternalInterface.addCallback('startFileUpload', uploadify_uploadFiles);
596 ExternalInterface.addCallback('cancelFileUpload', uploadify_cancelFileUpload);
597 ExternalInterface.addCallback('clearFileUploadQueue', uploadify_clearFileUploadQueue);
View Code

  现在我们能够得出这样一个结论:Uploadify本质上是一个基于Flash的jQuery上传插件.那么它到底能不能跨域呢?这里我们要考虑两个安全模型.一个是浏览器的同源策略,jQuery与目标服务器的交互是过Jsonp方式来实现回避浏览器的同源策略。还有一个就是Flash的安全沙箱,分析之前我们还是先完成金色海洋想要的实验.

 

环境准备

       我们在IIS中部署两个站点,既然是验证跨域我们为这两个站点绑定主机头;

   站点A:www.a.com 端口83 站点B:www.b.com 端口84

   

   修改Host文件(文件位置c:\Windows\System32\drivers\etc\hosts)

 

127.0.0.1 www.a.com

 

127.0.0.1 www.b.com

   注意:为了避免偶然因素的影响,后面每一次修改之后我都会重启IIS,使用新的浏览器窗口进行测试。

 

  1. 首先验证两个站点是否正常运行:站点A使用'script': 'http://www.a.com:83/Uploader.ashx', 站点B使用'script': 'http://www.b.com:84/Uploader.ashx',即当前域页面上传到当前域.测试通过
  2. 将站点A上传的目标服务域修改成站点B,即修改'script': 'http://www.b.com:84/Uploader.ashx',测试结果见下面的截图

error 

    3.看到上面的Security Error了么,我们通过在站点B下面添加一个crossdomain.xml,该文件的内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cross-domain-policy SYSTEM  "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd" >  
<cross-domain-policy>  <site-control permitted-cross-domain-policies="all" />  <allow-access-from domain="*" />  <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

添加了这个文件之后,站点A上传文件到站点B成功!

Uploadify跨域原理

      上面通过添加了crossdomain.xml之后就实现了跨域上传文件,关键点在于Flash的安全沙箱策略;Flash安全策略简单讲:同一个域的属于同一个沙箱,同一个沙箱的可以互相访问.如果要访问另外一个沙箱的内容就要在另外一个沙箱定义信任,这种信任策略就定义在crossdomain.xml中。在我们的实验中就是在站点B的策略文件crossdomain.xml中定义了对站点A的信任,只不过我偷懒让站点B信任所有外部域名的访问。

     对于crossdomain.xml还有两点细节:1.这个文件的要放在站点的根目录下而且文件名固定 2.跨域访问端口在1024以下必须要通过策略文件来定义信任关系。换句话说端口大于等于1024隐式开放访问权限。策略文件的详细说明请点击这里查看。

总结   

    对于金色海洋的问题解答:之所以你可以上传到另外一个端口的站点时因为IP一样,如果是上传到另外一个域名下,需要再目标服务器的根目录下添加Flash安全策略文件.

     Uploadify本质上是一个基于Flash的jQuery上传插件.跨域上传的情况牵扯到两个安全模型,一个使浏览器的同源策略,一个使是Flash的安全沙箱策略;我们组合使用jQuery的Jsonp和策略文件实现了跨域上传.

     好吧,就到这里,周末愉快

 

     测试文件下载:Web1.rar crossdomain.xml

 

转载于:https://www.cnblogs.com/xzxBlog/p/4625038.html

这篇关于Uploadify跨域上传原理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/228021

相关文章

Python中使用uv创建环境及原理举例详解

《Python中使用uv创建环境及原理举例详解》uv是Astral团队开发的高性能Python工具,整合包管理、虚拟环境、Python版本控制等功能,:本文主要介绍Python中使用uv创建环境及... 目录一、uv工具简介核心特点:二、安装uv1. 通过pip安装2. 通过脚本安装验证安装:配置镜像源(可

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Mysql的主从同步/复制的原理分析

《Mysql的主从同步/复制的原理分析》:本文主要介绍Mysql的主从同步/复制的原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录为什么要主从同步?mysql主从同步架构有哪些?Mysql主从复制的原理/整体流程级联复制架构为什么好?Mysql主从复制注意

Nacos注册中心和配置中心的底层原理全面解读

《Nacos注册中心和配置中心的底层原理全面解读》:本文主要介绍Nacos注册中心和配置中心的底层原理的全面解读,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录临时实例和永久实例为什么 Nacos 要将服务实例分为临时实例和永久实例?1.x 版本和2.x版本的区别

apache的commons-pool2原理与使用实践记录

《apache的commons-pool2原理与使用实践记录》ApacheCommonsPool2是一个高效的对象池化框架,通过复用昂贵资源(如数据库连接、线程、网络连接)优化系统性能,这篇文章主... 目录一、核心原理与组件二、使用步骤详解(以数据库连接池为例)三、高级配置与优化四、典型应用场景五、注意事

Java 中的跨域问题解决方法

《Java中的跨域问题解决方法》跨域问题本质上是浏览器的一种安全机制,与Java本身无关,但Java后端开发者需要理解其来源以便正确解决,下面给大家介绍Java中的跨域问题解决方法,感兴趣的朋友一起... 目录1、Java 中跨域问题的来源1.1. 浏览器同源策略(Same-Origin Policy)1.

GitLab文件的上传与下载方式

《GitLab文件的上传与下载方式》:本文主要介绍GitLab文件的上传与下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录GitLab 项目拉取到本地GitLab 项目上传方法方法 1:本地项目未初始化Git方法 2:本地项目已初始化GitGitLab 上

电脑系统Hosts文件原理和应用分享

《电脑系统Hosts文件原理和应用分享》Hosts是一个没有扩展名的系统文件,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Hosts文件中寻找对应的IP地址,一旦找到,系统会立即打开对应... Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应

Nginx 413修改上传文件大小限制的方法详解

《Nginx413修改上传文件大小限制的方法详解》在使用Nginx作为Web服务器时,有时会遇到客户端尝试上传大文件时返回​​413RequestEntityTooLarge​​... 目录1. 理解 ​​413 Request Entity Too Large​​ 错误2. 修改 Nginx 配置2.1

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中