diff --git a/src/ntqqapi/constructor.ts b/src/ntqqapi/constructor.ts
index 969f6ca..06bb2d2 100644
--- a/src/ntqqapi/constructor.ts
+++ b/src/ntqqapi/constructor.ts
@@ -76,8 +76,9 @@ export class SendMsgElementConstructor {
     if (fileSize === 0) {
       throw '文件异常,大小为0'
     }
-    if (fileSize > 1000 * 1000 * 7){  // todo: 没有采用1024计算,因为具体上限数值未知,大概是7MB
-      throw `图片过大,最大支持7MB,当前文件大小${fileSize}B`
+    const maxMB = 30;
+    if (fileSize > 1024 * 1024 * 30){
+      throw `图片过大,最大支持${maxMB}MB,当前文件大小${fileSize}B`
     }
     const imageSize = await NTQQFileApi.getImageSize(picPath)
     const picElement = {
@@ -134,8 +135,9 @@ export class SendMsgElementConstructor {
     if (fileSize === 0) {
       throw '文件异常,大小为0'
     }
-    if (fileSize > 1000 * 1000 * 100) {  // todo: 没有采用1024计算,因为具体上限数值未知,大概是100MB
-      throw `视频过大,最大支持100MB,当前文件大小${fileSize}B`
+    const maxMB = 100;
+    if (fileSize > 1024 * 1024 * maxMB) {
+      throw `视频过大,最大支持${maxMB}MB,当前文件大小${fileSize}B`
     }
     const pathLib = require('path')
     let thumbDir = path.replace(`${pathLib.sep}Ori${pathLib.sep}`, `${pathLib.sep}Thumb${pathLib.sep}`)
diff --git a/src/onebot11/action/msg/SendMsg.ts b/src/onebot11/action/msg/SendMsg.ts
index a0a769b..1bda604 100644
--- a/src/onebot11/action/msg/SendMsg.ts
+++ b/src/onebot11/action/msg/SendMsg.ts
@@ -50,22 +50,28 @@ function checkSendMessage(sendMsgList: OB11MessageData[]) {
       let data = msg['data']
       if (type === 'text' && !data['text']) {
         return 400
-      } else if (['image', 'voice', 'record'].includes(type)) {
+      }
+      else if (['image', 'voice', 'record'].includes(type)) {
         if (!data['file']) {
           return 400
-        } else {
+        }
+        else {
           if (checkUri(data['file'])) {
             return 200
-          } else {
+          }
+          else {
             return 400
           }
         }
-      } else if (type === 'at' && !data['qq']) {
-        return 400
-      } else if (type === 'reply' && !data['id']) {
+      }
+      else if (type === 'at' && !data['qq']) {
         return 400
       }
-    } else {
+      else if (type === 'reply' && !data['id']) {
+        return 400
+      }
+    }
+    else {
       return 400
     }
   }
@@ -87,10 +93,12 @@ export function convertMessage2List(message: OB11MessageMixType, autoEscape = fa
           },
         },
       ]
-    } else {
+    }
+    else {
       message = decodeCQCode(message.toString())
     }
-  } else if (!Array.isArray(message)) {
+  }
+  else if (!Array.isArray(message)) {
     message = [message]
   }
   return message
@@ -108,179 +116,177 @@ export async function createSendElements(
       continue
     }
     switch (sendMsg.type) {
-      case OB11MessageDataType.text:
-        {
-          const text = sendMsg.data?.text
-          if (text) {
-            sendElements.push(SendMsgElementConstructor.text(sendMsg.data!.text))
-          }
+      case OB11MessageDataType.text: {
+        const text = sendMsg.data?.text
+        if (text) {
+          sendElements.push(SendMsgElementConstructor.text(sendMsg.data!.text))
         }
+      }
         break
-      case OB11MessageDataType.at:
-        {
-          if (!target) {
-            continue
+      case OB11MessageDataType.at: {
+        if (!target) {
+          continue
+        }
+        let atQQ = sendMsg.data?.qq
+        if (atQQ) {
+          atQQ = atQQ.toString()
+          if (atQQ === 'all') {
+            // todo:查询剩余的at全体次数
+            const groupCode = (target as Group)?.groupCode
+            let remainAtAllCount = 1
+            let isAdmin: boolean = true
+            if (groupCode) {
+              try {
+                remainAtAllCount = (await NTQQGroupApi.getGroupAtAllRemainCount(groupCode)).atInfo
+                  .RemainAtAllCountForUin
+                log(`群${groupCode}剩余at全体次数`, remainAtAllCount)
+                const self = await getGroupMember((target as Group)?.groupCode, selfInfo.uin)
+                isAdmin = self.role === GroupMemberRole.admin || self.role === GroupMemberRole.owner
+              } catch (e) {
+              }
+            }
+            if (isAdmin && remainAtAllCount > 0) {
+              sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员'))
+            }
           }
-          let atQQ = sendMsg.data?.qq
-          if (atQQ) {
-            atQQ = atQQ.toString()
-            if (atQQ === 'all') {
-              // todo:查询剩余的at全体次数
-              const groupCode = (target as Group)?.groupCode
-              let remainAtAllCount = 1
-              let isAdmin: boolean = true
-              if (groupCode) {
-                try {
-                  remainAtAllCount = (await NTQQGroupApi.getGroupAtAllRemainCount(groupCode)).atInfo
-                    .RemainAtAllCountForUin
-                  log(`群${groupCode}剩余at全体次数`, remainAtAllCount)
-                  const self = await getGroupMember((target as Group)?.groupCode, selfInfo.uin)
-                  isAdmin = self.role === GroupMemberRole.admin || self.role === GroupMemberRole.owner
-                } catch (e) {}
-              }
-              if (isAdmin && remainAtAllCount > 0) {
-                sendElements.push(SendMsgElementConstructor.at(atQQ, atQQ, AtType.atAll, '全体成员'))
-              }
-            } else {
-              // const atMember = group?.members.find(m => m.uin == atQQ)
-              const atMember = await getGroupMember((target as Group)?.groupCode, atQQ)
-              if (atMember) {
-                sendElements.push(
-                  SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick),
-                )
-              }
+          else {
+            // const atMember = group?.members.find(m => m.uin == atQQ)
+            const atMember = await getGroupMember((target as Group)?.groupCode, atQQ)
+            if (atMember) {
+              sendElements.push(
+                SendMsgElementConstructor.at(atQQ, atMember.uid, AtType.atUser, atMember.cardName || atMember.nick),
+              )
             }
           }
         }
+      }
         break
-      case OB11MessageDataType.reply:
-        {
-          let replyMsgId = sendMsg.data.id
-          if (replyMsgId) {
-            const replyMsg = await dbUtil.getMsgByShortId(parseInt(replyMsgId))
-            if (replyMsg) {
+      case OB11MessageDataType.reply: {
+        let replyMsgId = sendMsg.data.id
+        if (replyMsgId) {
+          const replyMsg = await dbUtil.getMsgByShortId(parseInt(replyMsgId))
+          if (replyMsg) {
+            sendElements.push(
+              SendMsgElementConstructor.reply(
+                replyMsg.msgSeq,
+                replyMsg.msgId,
+                replyMsg.senderUin,
+                replyMsg.senderUin,
+              ),
+            )
+          }
+        }
+      }
+        break
+      case OB11MessageDataType.face: {
+        const faceId = sendMsg.data?.id
+        if (faceId) {
+          sendElements.push(SendMsgElementConstructor.face(parseInt(faceId)))
+        }
+      }
+        break
+      case OB11MessageDataType.mface: {
+        sendElements.push(
+          SendMsgElementConstructor.mface(
+            sendMsg.data.emoji_package_id,
+            sendMsg.data.emoji_id,
+            sendMsg.data.key,
+            sendMsg.data.summary,
+          ),
+        )
+      }
+        break
+      case OB11MessageDataType.image:
+      case OB11MessageDataType.file:
+      case OB11MessageDataType.video:
+      case OB11MessageDataType.voice: {
+        const data = (sendMsg as OB11MessageFile).data
+        let file = data.file
+        const payloadFileName = data?.name
+        if (file) {
+          const cache = await dbUtil.getFileCache(file)
+          if (cache) {
+            if (fs.existsSync(cache.filePath)) {
+              file = 'file://' + cache.filePath
+            }
+            else if (cache.downloadFunc) {
+              await cache.downloadFunc()
+              file = cache.filePath
+            }
+            else if (cache.url) {
+              file = cache.url
+            }
+            log('找到文件缓存', file)
+          }
+          const { path, isLocal, fileName, errMsg } = await uri2local(file)
+          if (errMsg) {
+            throw errMsg
+          }
+          if (path) {
+            if (!isLocal) {
+              // 只删除http和base64转过来的文件
+              deleteAfterSentFiles.push(path)
+            }
+            if (sendMsg.type === OB11MessageDataType.file) {
+              log('发送文件', path, payloadFileName || fileName)
+              sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName))
+            }
+            else if (sendMsg.type === OB11MessageDataType.video) {
+              log('发送视频', path, payloadFileName || fileName)
+              let thumb = sendMsg.data?.thumb
+              if (thumb) {
+                let uri2LocalRes = await uri2local(thumb)
+                if (uri2LocalRes.success) {
+                  thumb = uri2LocalRes.path
+                }
+              }
+              sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb))
+            }
+            else if (sendMsg.type === OB11MessageDataType.voice) {
+              sendElements.push(await SendMsgElementConstructor.ptt(path))
+            }
+            else if (sendMsg.type === OB11MessageDataType.image) {
               sendElements.push(
-                SendMsgElementConstructor.reply(
-                  replyMsg.msgSeq,
-                  replyMsg.msgId,
-                  replyMsg.senderUin,
-                  replyMsg.senderUin,
+                await SendMsgElementConstructor.pic(
+                  path,
+                  sendMsg.data.summary || '',
+                  <PicSubType>parseInt(sendMsg.data?.subType?.toString()) || 0,
                 ),
               )
             }
           }
         }
+      }
         break
-      case OB11MessageDataType.face:
-        {
-          const faceId = sendMsg.data?.id
-          if (faceId) {
-            sendElements.push(SendMsgElementConstructor.face(parseInt(faceId)))
+      case OB11MessageDataType.json: {
+        sendElements.push(SendMsgElementConstructor.ark(sendMsg.data.data))
+      }
+        break
+      case OB11MessageDataType.poke: {
+        let qq = sendMsg.data?.qq || sendMsg.data?.id
+        if (qq) {
+          if ('groupCode' in target) {
+            crychic.sendGroupPoke(target.groupCode, qq.toString())
           }
-        }
-        break
-      case OB11MessageDataType.mface:
-        {
-          sendElements.push(
-            SendMsgElementConstructor.mface(
-              sendMsg.data.emoji_package_id,
-              sendMsg.data.emoji_id,
-              sendMsg.data.key,
-              sendMsg.data.summary,
-            ),
-          )
-        }
-        break
-      case OB11MessageDataType.image:
-      case OB11MessageDataType.file:
-      case OB11MessageDataType.video:
-      case OB11MessageDataType.voice:
-        {
-          const data = (sendMsg as OB11MessageFile).data
-          let file = data.file
-          const payloadFileName = data?.name
-          if (file) {
-            const cache = await dbUtil.getFileCache(file)
-            if (cache) {
-              if (fs.existsSync(cache.filePath)) {
-                file = 'file://' + cache.filePath
-              } else if (cache.downloadFunc) {
-                await cache.downloadFunc()
-                file = cache.filePath
-              } else if (cache.url) {
-                file = cache.url
-              }
-              log('找到文件缓存', file)
-            }
-            const { path, isLocal, fileName, errMsg } = await uri2local(file)
-            if (errMsg) {
-              throw errMsg
-            }
-            if (path) {
-              if (!isLocal) {
-                // 只删除http和base64转过来的文件
-                deleteAfterSentFiles.push(path)
-              }
-              if (sendMsg.type === OB11MessageDataType.file) {
-                log('发送文件', path, payloadFileName || fileName)
-                sendElements.push(await SendMsgElementConstructor.file(path, payloadFileName || fileName))
-              } else if (sendMsg.type === OB11MessageDataType.video) {
-                log('发送视频', path, payloadFileName || fileName)
-                let thumb = sendMsg.data?.thumb
-                if (thumb) {
-                  let uri2LocalRes = await uri2local(thumb)
-                  if (uri2LocalRes.success) {
-                    thumb = uri2LocalRes.path
-                  }
-                }
-                sendElements.push(await SendMsgElementConstructor.video(path, payloadFileName || fileName, thumb))
-              } else if (sendMsg.type === OB11MessageDataType.voice) {
-                sendElements.push(await SendMsgElementConstructor.ptt(path))
-              } else if (sendMsg.type === OB11MessageDataType.image) {
-                sendElements.push(
-                  await SendMsgElementConstructor.pic(
-                    path,
-                    sendMsg.data.summary || '',
-                    <PicSubType>parseInt(sendMsg.data?.subType?.toString()) || 0,
-                  ),
-                )
-              }
+          else {
+            if (!qq) {
+              qq = parseInt(target.uin)
             }
+            crychic.sendFriendPoke(qq.toString())
           }
+          sendElements.push(SendMsgElementConstructor.poke('', ''))
         }
+      }
         break
-      case OB11MessageDataType.json:
-        {
-          sendElements.push(SendMsgElementConstructor.ark(sendMsg.data.data))
-        }
+      case OB11MessageDataType.dice: {
+        const resultId = sendMsg.data?.result
+        sendElements.push(SendMsgElementConstructor.dice(resultId))
+      }
         break
-      case OB11MessageDataType.poke:
-        {
-          let qq = sendMsg.data?.qq || sendMsg.data?.id
-          if (qq) {
-            if ('groupCode' in target) {
-              crychic.sendGroupPoke(target.groupCode, qq.toString())
-            } else {
-              if (!qq) {
-                qq = parseInt(target.uin)
-              }
-              crychic.sendFriendPoke(qq.toString())
-            }
-            sendElements.push(SendMsgElementConstructor.poke('', ''))
-          }
-        }
-        break
-      case OB11MessageDataType.dice:
-        {
-          const resultId = sendMsg.data?.result
-          sendElements.push(SendMsgElementConstructor.dice(resultId))
-        }
-        break
-      case OB11MessageDataType.RPS:
-        {
-          const resultId = sendMsg.data?.result
-          sendElements.push(SendMsgElementConstructor.rps(resultId))
-        }
+      case OB11MessageDataType.RPS: {
+        const resultId = sendMsg.data?.result
+        sendElements.push(SendMsgElementConstructor.rps(resultId))
+      }
         break
     }
   }
@@ -300,10 +306,34 @@ export async function sendMsg(
   if (!sendElements.length) {
     throw '消息体无法解析,请检查是否发送了不支持的消息类型'
   }
-  const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, 20000)
+  // 计算发送的文件大小
+  let totalSize = 0
+  for (const fileElement of sendElements) {
+    try {
+      if (fileElement.elementType === ElementType.PTT) {
+        totalSize += fs.statSync(fileElement.pttElement.filePath).size
+      }
+      if (fileElement.elementType === ElementType.FILE) {
+        totalSize += fs.statSync(fileElement.fileElement.filePath).size
+      }
+      if (fileElement.elementType === ElementType.VIDEO) {
+        totalSize += fs.statSync(fileElement.videoElement.filePath).size
+      }
+      if (fileElement.elementType === ElementType.PIC) {
+        totalSize += fs.statSync(fileElement.picElement.sourcePath).size
+      }
+    } catch (e) {
+      log('文件大小计算失败', e, fileElement)
+    }
+  }
+  log('发送消息总大小', totalSize, 'bytes')
+  let timeout = ((totalSize / 1024 / 512) * 1000) || 5000  // 512kb/s
+  log('设置消息超时时间', timeout)
+  const returnMsg = await NTQQMsgApi.sendMsg(peer, sendElements, waitComplete, timeout)
   log('消息发送结果', returnMsg)
   returnMsg.msgShortId = await dbUtil.addMsg(returnMsg)
-  deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
+  deleteAfterSentFiles.map((f) => fs.unlink(f, () => {
+  }))
   return returnMsg
 }
 
@@ -402,7 +432,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
       } catch (e) {
         throw '发送转发消息失败 ' + e.toString()
       }
-    } else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) {
+    }
+    else if (this.getSpecialMsgNum(messages, OB11MessageDataType.music)) {
       const music = messages[0] as OB11MessageMusic
       if (music) {
         const { musicSignUrl } = getConfigUtil().getConfig()
@@ -439,7 +470,7 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
         let jsonContent: string
         try {
           jsonContent = await new MusicSign(musicSignUrl).sign(postData)
-          if (!jsonContent){
+          if (!jsonContent) {
             throw '音乐消息生成失败,提交内容有误或者签名服务器签名失败'
           }
         } catch (e) {
@@ -459,7 +490,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
       }
     }
     const returnMsg = await sendMsg(peer, sendElements, deleteAfterSentFiles)
-    deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
+    deleteAfterSentFiles.map((f) => fs.unlink(f, () => {
+    }))
     return { message_id: returnMsg.msgShortId }
   }
 
@@ -562,7 +594,8 @@ export class SendMsg extends BaseAction<OB11PostSendMsg, ReturnDataType> {
             await sleep(500)
             log('转发节点生成成功', nodeMsg.msgId)
           }
-          deleteAfterSentFiles.map((f) => fs.unlink(f, () => {}))
+          deleteAfterSentFiles.map((f) => fs.unlink(f, () => {
+          }))
         } catch (e) {
           log('生成转发消息节点失败', e)
         }