Exemplo n.º 1
0
        /// <summary>
        /// 保存请求中的文件流
        /// </summary>
        /// <param name="fileUploadRequest"></param>
        /// <param name="rootPath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static HttpFile SaveFile(HttpListenerRequest fileUploadRequest, string rootPath, Encoding encoding)
        {
            HttpFile uploadFile = null;

            //判断上传文件大小,默认大小不能超过50M
            long contentLength = Convert.ToInt64(fileUploadRequest.Headers["Content-Length"]);
            if (contentLength > 1024 * 1024 * 50)
                Log.Comment(CommentType.Error, "上传文件大小不能超过50M,文件上传失败!");
            else if (rootPath == null)
                Log.Comment(CommentType.Error, "文件存放路径未设置,文件上传失败!");
            else
            {
                //获取文件分隔符
                string boundary = fileUploadRequest.ContentType.Split(';')[1];
                int endBoundaryLength = boundary.Length - 6;

                byte[] buffer = new byte[1024]; //缓冲数组,可设定任意大小,设定过小可能导致文件上传速度慢
                int headLength = 0; //上传文件头信息长度
                int singleReadLength = 0; //单次输入流中读取的长度
                int bufferLength = 0; //当前buffer使用的长度
                bufferLength = singleReadLength = fileUploadRequest.InputStream.Read(buffer, 0, buffer.Length);
                int startPos = -1;

                byte[] headByte = new byte[2048]; //文件头长度默认大小,假定文件头部最大长度不超过2048
                if (singleReadLength < 1)
                    Log.Comment(CommentType.Error, "文件流读取失败!");

                while (singleReadLength > 0)
                {
                    //找到文件主体部分分隔符,两个换行符,字节数组为{13,10,13,10}
                    startPos = IndexOf(buffer, bufferLength, new byte[4] { 13, 10, 13, 10 });

                    if (startPos >= 0)
                    {
                        Array.Copy(buffer, 0, headByte, headLength, startPos);
                        headLength += startPos;

                        string headString = encoding.GetString(headByte, 0, headLength);
                        string contentDisposition = headString.Split('\n')[1];

                        uploadFile = new HttpFile();
                        int posFileName = contentDisposition.IndexOf("filename=");
                        uploadFile.OriginName = contentDisposition.Substring(posFileName + 10, contentDisposition.Length - posFileName - 12);
                        int posPoint = uploadFile.OriginName.LastIndexOf('.');
                        string fileExtention = posPoint > -1 ? uploadFile.OriginName.Substring(posPoint) : null;  //文件扩展名

                        //生成guid命名文件,防止服务器文件重名
                        string subFolder = DateTime.Now.ToShortDateString();
                        uploadFile.RelativePath = Path.Combine(subFolder, Guid.NewGuid().ToString() + fileExtention);

                        string completePath = Path.Combine(rootPath, subFolder);
                        if (!Directory.Exists(completePath))
                            Directory.CreateDirectory(completePath);
                        using (FileStream saveStream = new FileStream(Path.Combine(rootPath, uploadFile.RelativePath), FileMode.Create, FileAccess.Write))
                        {
                            //数据流总长度,去掉头部和分隔符和文件结束边界和当前读取的文件数据部分,就是剩余要读取的文件数据部分长度
                            //int remainFileLength = (int)contentLength - (headLength + 4 + endBoundaryLength) - (bufferLength - startPos - 4);
                            int remainFileLength = (int)contentLength - headLength - endBoundaryLength - bufferLength + startPos;
                            int fileStartPos = startPos + 4;
                            saveStream.Write(buffer, fileStartPos, bufferLength - fileStartPos);
                            while (remainFileLength > 0)
                            {
                                singleReadLength = fileUploadRequest.InputStream.Read(buffer, 0, buffer.Length < remainFileLength ? buffer.Length : remainFileLength);
                                saveStream.Write(buffer, 0, singleReadLength);
                                remainFileLength -= singleReadLength;
                            }
                            //此时,文件数据部分已经读取完毕,数据流中还有文件结束边界没读取,此时没必要继续读,直接把singleReadLength设为0,结束循环
                            singleReadLength = 0;
                        }
                    }
                    else
                    {
                        //最后三个字符中可能含有分隔符,所以拷贝长度为当前读取长度减3
                        int copyLength = bufferLength - 3;
                        Array.Copy(buffer, 0, headByte, headLength, copyLength);
                        headLength += copyLength;

                        //最后三个字符不足匹配长度,放到新的缓冲里面继续匹配
                        buffer[0] = buffer[bufferLength - 3];
                        buffer[1] = buffer[bufferLength - 2];
                        buffer[2] = buffer[bufferLength - 1];
                        singleReadLength = fileUploadRequest.InputStream.Read(buffer, 3, buffer.Length - 3);
                        bufferLength = singleReadLength + 3;
                    }
                }
            }

            return uploadFile;
        }