84年的矿泉水

博客园 首页 新随笔 联系 订阅 管理

      昨天完成了dfs批量上传文件的服务器端程序,再第一时间就拿出来共享了。当然了,程序比较乱,那是因为我调试的一些信息都留在里面了,是原汁原味的东西,包括一些注释什么的都没有删除,我认为这些东西应该能起到让人更快理解程序的作用,所以就全部放出来了。当然了也有可能注释的错的,大家见谅啊。

      今天完成了客户端程序,因为我主要是做net开发的,所以在dfs没有net客户端的情况下就自己按照我们的业务自己写了一个客户端,今天先把net的批上传文件代码拿出来,也是原汁原味的,没有经过调试的时候任何更改的。

  /// <summary>
        /// 批量上传文件.
        /// </summary>
        /// <param name="groupName">Name of the group.</param>
        /// <param name="filesCount">The files count.</param>
        /// <param name="localFileName">Name of the local file.</param>
        /// <param name="buffer">The buffer.</param>
        /// <param name="extension">The extension.</param>
        /// <returns></returns>
        protected static string[] DoBatchUpload(string groupName, IList<byte[]> filesBuffer, string[] filesExtension)
        {
            int filesCount = filesBuffer.Count;
            if (255 < filesCount)
            {
                if (null != _logger)
                {
                    _logger.ErrorFormat("批量上传文件的数量为:{0},超出了限定批上传文件数(限定批上传文件数为),请分多次上传.", filesCount);
                    throw new Exception("上传文件数超出批处理限制范围!");
                }
            }
            if (null != _logger)
            {
                _logger.InfoFormat("开始批量上传文件,批量上传文件的总数为:{0}.", filesCount);
            }
            TcpConnection storageConnection = GetStorageConnection(groupName);
            if (null != _logger)
                _logger.InfoFormat("Storage服务器的IP是:{0}.端口为{1}", storageConnection.IpAddress, storageConnection.Port);

            if (filesBuffer.Count != filesExtension.Length)
            {
                if (null != _logger)
                    _logger.ErrorFormat("上传文件数组与上传文件扩展名,上传文件数组长度为{0},文件扩展名数组长度为{1}。",
                        filesBuffer.Count, filesExtension.Length);
                throw new Exception("上传文件数不匹配。");
            }

            //构建扩展名传输流
            byte[] filesExtensionBuffer = new byte[Protocol.FDFS_FILE_EXT_NAME_MAX_LEN * filesCount];
            byte[] fileExtensionBuffer = new byte[Protocol.FDFS_FILE_EXT_NAME_MAX_LEN];
            byte[] fileTempExtensionBuffer;
            for (int i = 0; i < filesExtension.Length; i++)
            {
                if (string.IsNullOrEmpty(filesExtension[i]))
                {
                    if (null != _logger)
                        _logger.Error("文件扩展名为空,终止文件上传。");
                    throw new Exception("未获得文件扩展名。");
                }
                fileTempExtensionBuffer = Encoding.GetEncoding(FastDFSService.Charset).GetBytes(filesExtension[i]);
                int fileExtBufferLength = fileTempExtensionBuffer.Length;
                if (fileExtBufferLength > Protocol.FDFS_FILE_EXT_NAME_MAX_LEN) fileExtBufferLength = Protocol.FDFS_FILE_EXT_NAME_MAX_LEN;

                //协议归整
                Array.Copy(fileTempExtensionBuffer, 0, fileExtensionBuffer, 0, fileExtBufferLength);
                //加入网络传输
                Array.Copy(fileExtensionBuffer, 0, filesExtensionBuffer, i * Protocol.FDFS_FILE_EXT_NAME_MAX_LEN, fileExtBufferLength);
            }

            //构建文件传输流
            long filesBufferLength = 0L;
            foreach (byte[] fileBuffer in filesBuffer)
            {
                filesBufferLength += fileBuffer.LongLength;
            }
          
            //构建文件数量字节流
            byte[] filesCountBuffer = Util.LongToBuffer(filesCount);

            //构建头部协议块
            // Protocol.TRACKER_PROTO_PKG_LEN_SIZE * (filesCount + 2) 各个文件的长度+扩展名字节流的长度+文件字节流总共的长度
            byte[] headerBuffer = new byte[1 + Protocol.TRACKER_PROTO_PKG_LEN_SIZE * (filesCount + 2)];
            headerBuffer[0] = (byte)storageConnection.Index;//第一位为storage的index
            byte[] temp; 
            //每位表示每个文件的字节流长度
            for (int i = 0; i < filesBuffer.Count; i++)
            {
                temp = Util.LongToBuffer(filesBuffer[i].LongLength);
                Array.Copy(temp, 0, headerBuffer, 1 + i * Protocol.TRACKER_PROTO_PKG_LEN_SIZE, temp.LongLength);
            }

            temp = Util.LongToBuffer(filesExtensionBuffer.LongLength);//扩展名总共的长度
            Array.Copy(temp, 0, headerBuffer, 1 + filesBuffer.Count * Protocol.TRACKER_PROTO_PKG_LEN_SIZE, temp.LongLength);
            temp = Util.LongToBuffer(filesBufferLength);//文件字节流长度
            Array.Copy(temp, 0, headerBuffer, 1 + (filesBuffer.Count + 1) * Protocol.TRACKER_PROTO_PKG_LEN_SIZE, temp.LongLength);

            //构建协议传输流
            byte[] protocalBuffer = Util.PackHeader(Protocol.STORAGE_PROTO_CMD_Batch_UPLOAD,
                //长度构成:一位storage的index+每个文件的字节长度+文件扩展名的总长度+文件字节的总长度
                                               headerBuffer.Length +
                                               filesCountBuffer.Length
                                              + filesExtensionBuffer.Length + filesBufferLength,
                                               0);

            _logger.InfoFormat("上传字节数为:{0}", headerBuffer.Length +
                                               filesCountBuffer.Length
                                              + filesExtensionBuffer.Length + filesBufferLength);

            Stream outStream = storageConnection.GetStream();
            outStream.Write(protocalBuffer, 0, protocalBuffer.Length);
            outStream.Write(filesCountBuffer, 0, filesCountBuffer.Length);
            outStream.Write(headerBuffer, 0, headerBuffer.Length);
            outStream.Write(filesExtensionBuffer, 0, filesExtensionBuffer.Length);
            foreach (byte[] buffer in filesBuffer)
            {
                outStream.Write(buffer,0,buffer.Length);
            }

            Stream readStream;
            int fileNameBufferLength = Protocol.TRACKER_PROTO_PKG_LEN_SIZE + 128;//文件名长度+文件名内容
            byte[] tempBuffer;
            int tempReadSize = 0;
            int fileNameSize;
            byte[] tempFileNameBytes;
            char[] chars;
            int error;
            string[] filesName = new string[filesCount];
            for(int i = 0;i<filesCount;i++)
            {
                readStream = storageConnection.GetStream();
                tempBuffer = new byte[Protocol.TRACKER_PROTO_PKG_LEN_SIZE + 128];
                tempReadSize = readStream.Read(tempBuffer, 0, fileNameBufferLength);
                if(tempReadSize != fileNameBufferLength)
                {
                    if(tempReadSize == 10)//文件未传输完成出现错误
                    {
                        error = tempBuffer[Protocol.PROTO_HEADER_STATUS_INDEX];
                        if (null != _logger)
                            _logger.ErrorFormat("上传文件中间发生异常,文件位置为:{0}.错误号为:{1}", i + 1, error);
                        throw new Exception("上传文件错误!");
                    }
                    if (null != _logger)
                        _logger.ErrorFormat("上传文件中间发生异常,文件位置为:{0}.未能返回错误号,错误header长度为:{1}", i + 1, tempReadSize);
                    throw new Exception("上传文件错误!");
                }

                fileNameSize = (int)Util.BufferToLong(tempBuffer, 0);
                tempFileNameBytes = new byte[fileNameSize];
                Array.Copy(tempBuffer, Protocol.TRACKER_PROTO_PKG_LEN_SIZE, tempFileNameBytes, 0, fileNameSize);
                chars = Util.ToCharArray(tempFileNameBytes);
                filesName[i] = new string(chars, 0, fileNameSize).Trim('\0').Trim();

            }
            readStream = storageConnection.GetStream();
            tempBuffer = new byte[10];
            tempReadSize = readStream.Read(tempBuffer, 0, 10);
            if (10 != tempReadSize)
            {
                if (null != _logger)
                    _logger.ErrorFormat("文件上传完毕,并且文件路径已经全部返回客户端。但是发生服务器传输信息头错误。错误header长度为:{0}", tempReadSize);
            }

            error = tempBuffer[Protocol.PROTO_HEADER_STATUS_INDEX];
            if (0 != error)
            {
                if (null != _logger)
                    _logger.ErrorFormat("文件上传完毕,并且文件路径已经全部返回客户端。但是服务器发生错误。错误号:{0}",error);
            }

            return filesName;
        }
 

       写这个程序的时候呢,因为是和服务器端程序一并调试用的,所以主要考虑了程序的完成功能程度,没有考虑性能,clr-gc等等这些东西。但是性能应该不会太差,clr的gc可能会忙一点。大家有兴趣的话,可以自己优化一下,其实这种东西不难的。

posted on 2010-02-04 10:12  xvhfeng  阅读(1186)  评论(0编辑  收藏  举报