附件
-
会在数据库的
fileuploads
表里有记录{ "_id" : "-W1iX9nmOTM", ... "location" : "uploads\\7fwwex6z4y4tg", }
-
mesages
表里的记录有fileuploads
对应的_id
字段- /v0/file/s/-W1iX9nmOTM.jpg
- 上面的链接也是前端发送给后端的,后端根据
-W1iX9nmOTM.jpg
找到fileuploads._id
的记录然后根据location
字段提供下载
-
在
server/store/store.go
里的Save里处理,记录到fileuploads
表里也在这里处理的func (MessagesObjMapper) Save(msg *types.Message, readBySender bool) error { if header, ok := msg.Head["attachments"]; ok { ... } }
-
太大的文件不能发送
-
如果token的时效设的太短,那么会导致失败,因为要提供token
直接发送图片
和客户端的交互记录
2020/03/30 17:03:47 in: {"pub":{"id":"98368","topic":"usry8McI40hGwk","noecho":true,"head":{"mime":"text/x-drafty"},"content":{"txt":" ","ent":[{"tp":"IM","data":{"mime":"image/png","val":"iVBORw0KGgoAAAANSUhEUgAAAs8AAAGlCAYAAAAF9RsWAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAK0mSURBVHhe7Z0vsB1luq+vG8c4XDAQQxyYSwwUglzMYGYuhsIwmGTEqWAYDFRMYoaMuCnESRQxSWESBSNOKiZgDoo5BsYMDnePu2rf/SzWL/Pud3//utdae+3e+T1VXcleq/v7391Pv+vr7v9xyIEXL168ePHixYsXL16Glv9xYJaD+8sYY4wxZj9YnheI+8sYY4wxZj9YnheI+8sYY4wxZj9YnheI+8sYY4wxZj9<...>"}}]}}}'
2020/03/30 17:03:47 out: mt = `1`, `{"ctrl":{"id":"98368","topic":"usry8McI40hGwk","params":{"seq":32},"code":202,"text":"accepted","ts":"2020-03-30T09:03:47.813Z"}}`
2020/03/30 17:03:47 out: mt = `1`, `{"data":{"topic":"usrJnmU7EGAAX4","from":"usrJnmU7EGAAX4","ts":"2020-03-30T09:03:47.813Z","seq":32,"head":{"mime":"text/x-drafty"},"content":{"ent":[{"data":{"height":421,"mime":"image/png","name":"微信图片_20200104162412.png","val":"","width":719},"tp":"IM"}],"fmt":[{"len":1}],"txt":" "}}}`
2020/03/30 17:03:48 in: '{"note":{"topic":"usrJnmU7EGAAX4","what":"recv","seq":32}}' ip='127.0.0.1:57030'
2020/03/30 17:03:48 out: mt = `1`, `{"info":{"topic":"usry8McI40hGwk","from":"usry8McI40hGwk","what":"recv","seq":32}}`
2020/03/30 17:03:49 in: '{"note":{"topic":"usry8McI40hGwk","what":"read","seq":32}}' ip='127.0.0.1:56702'
2020/03/30 17:03:49 in: '{"note":{"topic":"usrJnmU7EGAAX4","what":"read","seq":32}}' ip='127.0.0.1:57030'
2020/03/30 17:03:49 out: mt = `1`, `{"info":{"topic":"usry8McI40hGwk","from":"usry8McI40hGwk","what":"read","seq":32}}`
图片链接
- 发送方的地址: blob:http://127.0.0.1:6060/5740db06-cb63-4bfd-95eb-cc4e4992eb77
- 接受方的地址: blob:http://127.0.0.1:6060/f0cff750-171c-4d46-9c4e-30767d3a50ec
- 这2个地址只能在各自的浏览器里展现,在其他地方都是无法打开,原因见下面的
blob
- chrome提示
找不到您的文件该文件可能已被移至别处或遭到删除。 ERR_FILE_NOT_FOUND
- firfox提示
呃…这个网址好像有错。 请检查网址是否正确,然后重试。
- chrome提示
- 如果在能打开的地方,地址前缀不使用
blob:http://
,只使用http://
会提示{ ctrl: { code: 404, text: "Not Found", ts: "2020-03-31T07:30:10.44Z" } }
blob协议
- 一般的用法是用来预览图片: blob例子
- 做到和tinode一样在同一个浏览器新的标签页也可以访问图片,把这个url放到全局对象上:
let u = window.URL.createObjectURL(e.target.files[0]) console.log("可以全局访问的对象",u);
- 做到和tinode一样在同一个浏览器新的标签页也可以访问图片,把这个url放到全局对象上:
- Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据: MDN-blob
- 应该只是在前端,其实不涉及后端
疑问
- 这个图片放在哪儿了?
- 是直接发送的二进制数据,这些数据作为聊天内容的一部分是放在数据库的
图片链接
是怎么生成的?- 见上面的blob
- pub后是怎么处理这个消息的,看到是直接塞到sub的一个channel了
-
在有sub的情况下的处理代码
if sub := s.getSub(expanded); sub != nil { // This is a post to a subscribed topic. The message is sent to the topic only log.Printf("sub != nil, sub = %+v", sub) sub.broadcast <- data }
-
sub对应的数据结构
// Subscription is a mapper of sessions to topics. type Subscription struct { // Channel to communicate with the topic, copy of Topic.broadcast broadcast chan<- *ServerComMessage // 这个channel只能塞,没法取啊,怎么跟topic关联上的? // Session sends a signal to Topic when this session is unsubscribed // This is a copy of Topic.unreg done chan<- *sessionLeave // Channel to send {meta} requests, copy of Topic.meta meta chan<- *metaReq // Channel to ping topic with session's user agent uaChange chan<- string }
-
channel是引用类型,在
server/topic.go
里,作了引用类型的值传递,第一步
塞入到Subscription的sess.addSub(t.name, &Subscription{ broadcast: t.broadcast, // 这里作了2个channel类型的赋值,就是引用类型的值传递, done: t.unreg, meta: t.meta, uaChange: t.uaChange}) t.addSession(sess, asUid)
-
由
server/topic.go
里的run函数处理了func (t *Topic) run(hub *Hub) { case msg := <-t.broadcast: ... }
-