博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MSDN文档中的一个不那么和谐的示例
阅读量:5119 次
发布时间:2019-06-13

本文共 6167 字,大约阅读时间需要 20 分钟。

最近写网站用到FileUpload控件,好长时间不用手生了,所以特地又仔细地看了一遍MSDN文档。在看到其FileBytes属性时,看到其中的示例代码,颇感郁闷。

// 后面有给dudu的附言,如果有幸dudu莅临,请阅
感觉其中有不少问题,虽然很细微,但出现在MSDN中,总感却不那么和谐。
下面是完整的示例。

  1
None.gif
<%
@ Page Language
=
"
C#
"
 
%>
  2
None.gif
<
html
>
  3
None.gif
<
head
>
  4
None.gif
  5
None.gif    
<
script runat
=
"
server
"
>
  6
None.gif        
  7
None.gif        
private
 
void
 DisplayFileContents(HttpPostedFile file) 
  8
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{            
  9InBlock.gif            int fileLen;
 10InBlock.gif            string displayString = "";
 11InBlock.gif            
 12InBlock.gif            // Get the length of the file.
 13ExpandedSubBlockStart.gifContractedSubBlock.gif            fileLen = FileUpload1.PostedFile.ContentLength;    /**////<---- 1.1
 14ExpandedSubBlockEnd.gif            
 15InBlock.gif            // Display the length of the file in a label.
 16InBlock.gif            LengthLabel.Text = "The length of the file is "
 17InBlock.gif                               + fileLen.ToString() + " bytes.";
 18InBlock.gif            
 19InBlock.gif            // Create a byte array to hold the contents of the file.
 20InBlock.gif            byte[] input = new byte[fileLen];
 21ExpandedSubBlockStart.gifContractedSubBlock.gif            input = FileUpload1.FileBytes;                     /**////<---- 2, 1.2
 22ExpandedSubBlockEnd.gif            
 23InBlock.gif            // Copy the byte array to a string.
 24ExpandedSubBlockStart.gifContractedSubBlock.gif            for (int loop1 = 0; loop1 <= fileLen - 1; loop1++dot.gif{
 25ExpandedSubBlockStart.gifContractedSubBlock.gif                displayString = displayString + input[loop1].ToString();    /**////<---- 3
 26ExpandedSubBlockEnd.gif            }
 27InBlock.gif            
 28InBlock.gif            // Display the contents of the file in a 
 29InBlock.gif            // textbox on the page.
 30InBlock.gif            ContentsLabel.Text = "The contents of the file as bytes:";
 31InBlock.gif            
 32ExpandedSubBlockStart.gifContractedSubBlock.gif            TextBox ContentsTextBox = new TextBox();           /**////<---- 4
 33ExpandedSubBlockEnd.gif            ContentsTextBox.TextMode = TextBoxMode.MultiLine;
 34InBlock.gif            ContentsTextBox.Height = Unit.Pixel(300);
 35InBlock.gif            ContentsTextBox.Width = Unit.Pixel(400);
 36InBlock.gif            ContentsTextBox.Text = displayString;
 37InBlock.gif            
 38InBlock.gif            // Add the textbox to the Controls collection
 39InBlock.gif            // of the Placeholder control.
 40InBlock.gif            PlaceHolder1.Controls.Add(ContentsTextBox);
 41InBlock.gif
 42ExpandedSubBlockEnd.gif        }
 43InBlock.gif
 44InBlock.gif    protected void  UploadButton_Click(object sender, EventArgs e)
 45ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 46InBlock.gif            // Specify the path on the server to
 47InBlock.gif            // save the uploaded file to.
 48InBlock.gif            string savePath = @"c:\temp\uploads\";
 49InBlock.gif            
 50InBlock.gif            // Before attempting to perform operations
 51InBlock.gif            // on the the file, verify that the FileUpload 
 52InBlock.gif            // control contains a file.
 53ExpandedSubBlockStart.gifContractedSubBlock.gif            if (FileUpload1.HasFile) dot.gif{
 54InBlock.gif            
 55InBlock.gif                // Append the name of the file to upload to the path.
 56InBlock.gif                savePath += FileUpload1.FileName;
 57InBlock.gif            
 58InBlock.gif                // Call the SaveAs method to save the 
 59InBlock.gif                // uploaded file to the specified path.
 60InBlock.gif                // This example does not perform all
 61InBlock.gif                // the necessary error checking.               
 62InBlock.gif                // If a file with the same name
 63InBlock.gif                // already exists in the specified path,  
 64InBlock.gif                // the uploaded file overwrites it.
 65InBlock.gif                FileUpload1.SaveAs(savePath);
 66InBlock.gif                
 67InBlock.gif                // Notify the user that the file was uploaded successfully.
 68InBlock.gif                UploadStatusLabel.Text = "Your file was uploaded successfully.";
 69InBlock.gif                
 70InBlock.gif                // Call a helper routine to display the contents
 71InBlock.gif                // of the file to upload.
 72ExpandedSubBlockStart.gifContractedSubBlock.gif                DisplayFileContents(FileUpload1.PostedFile);    /**////<---- 1.3
 73ExpandedSubBlockEnd.gif            }
 74InBlock.gif            else
 75ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 76InBlock.gif                // Notify the user that a file was not uploaded.
 77InBlock.gif                UploadStatusLabel.Text = "You did not specify a file to upload.";
 78ExpandedSubBlockEnd.gif            }
 79ExpandedSubBlockEnd.gif    }
 80InBlock.gif</script>
 81InBlock.gif
 82InBlock.gif</head>
 83InBlock.gif<body>
 84InBlock.gif
 85InBlock.gif    <h3>FileUpload.FileContent Property Example</h3>
 86InBlock.gif
 87InBlock.gif    <form ID="Form1" runat="server">
 88InBlock.gif   
 89InBlock.gif        <h4>Select a file to upload:</h4>
 90InBlock.gif       
 91InBlock.gif        <asp:FileUpload id="FileUpload1"
 92InBlock.gif           runat="server">
 93InBlock.gif        </asp:FileUpload>
 94InBlock.gif       
 95InBlock.gif        <br /><br />
 96InBlock.gif       
 97InBlock.gif        <asp:Button id="UploadButton" 
 98InBlock.gif            Text="Upload file"
 99InBlock.gif            OnClick="UploadButton_Click"
100InBlock.gif            runat="server">
101InBlock.gif        </asp:Button>
102InBlock.gif        
103InBlock.gif        <br /><br />
104InBlock.gif        
105InBlock.gif        <asp:Label id="UploadStatusLabel"
106InBlock.gif           runat="server">
107InBlock.gif        </asp:Label>  
108InBlock.gif            
109InBlock.gif        <hr />
110InBlock.gif        
111InBlock.gif        <asp:Label id="LengthLabel"
112InBlock.gif           runat="server">
113InBlock.gif        </asp:Label>  
114InBlock.gif        
115InBlock.gif        <br /><br />
116InBlock.gif       
117InBlock.gif        <asp:Label id="ContentsLabel"
118InBlock.gif           runat="server">
119InBlock.gif        </asp:Label>  
120InBlock.gif        
121InBlock.gif        <br /><br />
122InBlock.gif       
123InBlock.gif        <asp:PlaceHolder id="PlaceHolder1"
124InBlock.gif            runat="server">
125InBlock.gif        </asp:PlaceHolder>         
126InBlock.gif         
127InBlock.gif    </form>
128InBlock.gif
129InBlock.gif</body>
130InBlock.gif</html>

问题1
注释中的1.1、1.2、1.3

None.gif
        
private
 
void
 DisplayFileContents(HttpPostedFile file) 
ExpandedBlockStart.gifContractedBlock.gif        
dot.gif
{            
InBlock.gif            
int fileLen;
InBlock.gif            
string displayString = "";
InBlock.gif            
InBlock.gif            
// Get the length of the file.
ExpandedSubBlockStart.gifContractedSubBlock.gif
            fileLen = FileUpload1.PostedFile.ContentLength;    /**////<---- 1.1
InBlock.gif

ExpandedBlockStart.gif
ContractedBlock.gif
            input 
=
 FileUpload1.FileBytes;                     
/**/
///<---- 2, 1.2
InBlock.gif

None.gif
    
protected
 
void
  UploadButton_Click(
object
 sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif
{
InBlock.gifdot.gif
InBlock.gif                
// Call a helper routine to display the contents
InBlock.gif                
// of the file to upload.
ExpandedSubBlockStart.gifContractedSubBlock.gif
                DisplayFileContents(FileUpload1.PostedFile);    /**////<---- 1.3
InBlock.gif

在这里,DisplayFileContents方法接受一个HttpPostedFile类型的参数file,表示从FileUpload控件上传的文件。的确,在1.3处将FileUpload1.PostedFile属性传了进来。

先往复杂了说,从方法的名字和参数可以猜想,作者的目的是降低显示文件内容的操作和FileUpload控件的耦合度。比如,如果页面上有多个FileUpload控件时,就可以重用该方法;或者如果不使用FileUpload控件了,而是用了自己编写的上传控件,只要能提供HttpPostedFile类型的对象,也可以使用该方法。但1.1和1.2两个地方颠覆了这个初衷,这个方法还是紧紧地与FileUpload1控件紧紧地关联在了一起。如果添加了另外一个FileUpload控件,或者原控件改名了,这个方法必须同时修改。
再往简单了说,整个方法体都没有用到过这个file参数,又何必添加呢?
问题2
注释中的2

None.gif
            
//
 Create a byte array to hold the contents of the file.
None.gif
            
byte
[] input 
=
 
new
 
byte
[fileLen];
ExpandedBlockStart.gifContractedBlock.gif            input 
=
 FileUpload1.FileBytes;                     
/**/
///<---- 2, 1.2
InBlock.gif

这是一个比较严重的内存泄露问题。首先,之前的一行byte[] input = new byte[fileLen];在堆上分配了与文件大小相同的字节数组(注意数组都是引用类型),然后input = FileUpload1.FileBytes;直接修改了input变量所引用的对象,而原来new byte[fileLen]得到的数组成了孤立对象,遗留在堆中等待被回收。

试想如果这个代码出现在产品中,如果允许用户数MB甚至更大的文件,如果同时(或很短一段时间内)有数百甚至更多的人上传文件……
改进方法:1 直接使用FileUpload1.FileBytes属性,或者直接作这样的赋值:byte[] input = FileUpload1.FileBytes,然后使用input变量;2 如果有必要用一个数组的话,写一个循环将FileUpload1.FileBytes的内容复制到input中。
问题3
注释中的3

None.gif
            
//
 Copy the byte array to a string.
ExpandedBlockStart.gifContractedBlock.gif
            
for
 (
int
 loop1 
=
 
0
; loop1 
<=
 fileLen 
-
 
1
; loop1
++
dot.gif
{
ExpandedSubBlockStart.gifContractedSubBlock.gif                displayString 
= displayString + input[loop1].ToString();    /**////<---- 3
InBlock.gif
            }
InBlock.gif

这也是一个比较严重的问题,但我就不用多说了,几乎提到了字符串操作的每篇技术文章或每本书都提到,慎用字符串的相加(连接)操作,尤其是在循环内部。

问题4

注释中的4

ExpandedBlockStart.gif
ContractedBlock.gif
            TextBox ContentsTextBox 
=
 
new
 TextBox();           
/**/
///<---- 4
ExpandedBlockEnd.gif
            ContentsTextBox.TextMode = TextBoxMode.MultiLine;
None.gif
            ContentsTextBox.Height 
=
 Unit.Pixel(
300
);
None.gif            ContentsTextBox.Width 
=
 Unit.Pixel(
400
);
None.gif            ContentsTextBox.Text 
=
 displayString;
None.gif            
None.gif            
//
 Add the textbox to the Controls collection
None.gif            
//
 of the Placeholder control.
None.gif
            PlaceHolder1.Controls.Add(ContentsTextBox);
None.gif

这是一个小问题,主要在于用户体验。每上传一次就要创建一个文本框显示文件内容,并且文本框是在服务器端添加的,刷新页面也无法消除。这样的话,如果用户查看了几个文件的内容后,要想清空页面,只有关闭浏览器重新打开,这样的用户体验是非常不好的。实际上,硬编码一个文本框,每次修改其Text属性即可。

----------- 分割线华丽地降临 -------------------
实际上,对于示例代码来说,问题1和4无伤大雅,毕竟受众所关心的是如何通过FileBytes得到文件中的字节。但问题2和3些许有些“误人子弟”(如果有人直接像这样读取文件字节,那就得浪费fileLen个字节的内存,如果有n个人用这个功能,那就得浪费n*fileLen个字节,你付得起责任吗?——小学老师如是教育)。而如果是在产品中,这4个问题恐怕都会产生不良后果。
----------- 分割线再次华丽地降临 ---------------
P.S.
to dudu:
园子的回复下面有一个“刷新评论列表”,实在是个好东西。
但有个问题,就是如果一篇文章一条回复也没有的话,这个链接是不会出现的。
可如果我在浏览一个 尚没有回复的文章 时,希望刷一下看看有没有人在我浏览的时候发表了回复,那就只有刷新页面了。
所以,能否改进一下,让这个链接任何时候都能出现?
小问题,呵呵~

转载于:https://www.cnblogs.com/AndersLiu/archive/2007/05/20/752889.html

你可能感兴趣的文章
iOS--控制器加载自定义view的xib
查看>>
java反射详解
查看>>
android蓝牙4.0(BLE)开发之ibeacon初步
查看>>
在Ubuntu上下载、编译和安装Android最新源代码
查看>>
串匹配数据结构-练习4 字符串匹配
查看>>
集成信息医院需要什么样的集成平台
查看>>
图片切换[置顶] 送大家几款可以运用到实际项目的flash+xml控件
查看>>
单片机开发 郭天祥
查看>>
抽象类和纯虚函数
查看>>
lua类对象
查看>>
去掉Html标签方法
查看>>
SecureStoreProvider扩展:验证Application中是否有当前用户的credentials
查看>>
用Visual Studio Code Debug世界上最好的语言
查看>>
CDN 服务域名解析配置
查看>>
eclipse使用git插件导入码云上的maven工程
查看>>
uuid-不好之处
查看>>
Codeforces Beta Round #96 (Div. 2) 133B. Unary(快速幂)
查看>>
IOS , plist 配置项说明
查看>>
IOS-小技巧总结,绝对有你想要的
查看>>
Android 蓝牙扫描代码
查看>>