Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Message GetFile() #31

Closed
suntong opened this issue Jul 15, 2021 · 12 comments
Closed

Using Message GetFile() #31

suntong opened this issue Jul 15, 2021 · 12 comments

Comments

@suntong
Copy link
Contributor

suntong commented Jul 15, 2021

Hi @eatmoreapple,

Do you have sample code how to use the func (*Message) GetFile and save it to disk please?

I assume it'll be another FAQ, and I don't know how you derive a file name for that GetFile. Thx!

@eatmoreapple
Copy link
Owner

请看示例

@eatmoreapple
Copy link
Owner

eatmoreapple commented Jul 17, 2021

bot.MessageHandler = func(msg *openwechat.Message) {
        if msg.IsPicture() {
	        resp, err := msg.GetFile()
	        if err != nil {
		        // handle err here
		        return
	        }
	        defer resp.Body.Close()
	        file, _ := os.Create("test.png")
	        defer file.Close()
	        io.Copy(file, resp.Body)
        
        }
}

@eatmoreapple
Copy link
Owner

dispatcher := openwechat.NewMessageMatchDispatcher()
dispatcher.OnImage(func(ctx *openwechat.MessageContext) {
        resp, err := ctx.GetFile()
        if err != nil {
	        // handle err here
	        return
        }
        defer resp.Body.Close()
        file, _ := os.Create("test.png")
        defer file.Close()
        io.Copy(file, resp.Body)
})
bot.MessageHandler = openwechat.DispatchMessage(dispatcher)

@eatmoreapple
Copy link
Owner

filename似乎是拿不到的

@suntong
Copy link
Contributor Author

suntong commented Jul 17, 2021

filename似乎是拿不到的

OK, no way to derive a file name for that GetFile function, but how about from the message itself? If there is an attachment, say a .pdf file, the file name is carried within the message itself right?

For the unnamed cases, like pictures, or voices, I found from
wechaty/puppet-padlocal@d402f49
that wechaty's practice is to use message-${messageId}-image-${imageNameSuffix}.jpg, just I don't know how to translate those variables into openwechat (yet), and I'm also not sure if the code is correct, as the pictures can be in .jpg or, .png or even .gif format, and it seems that fix only names everything as .jpg.

Thanks

@eatmoreapple
Copy link
Owner

messageId 可以用 msg.MediaId拿到 , 具体的文件类型你可以用 http.DetectContentType 这个方法来获取

@suntong
Copy link
Contributor Author

suntong commented Jul 19, 2021

Thanks a lot!

@suntong suntong closed this as completed Jul 19, 2021
@eatmoreapple
Copy link
Owner

有些类型的文件是可以拿到文件名的

resp, err := msg.GetFile()
if err != nil {
fmt.Println(err)
      return
}
defer resp.Body.Close()
fmt.Println(resp.Header.Get("Content-Disposition"))
name := strings.Replace(resp.Header.Get("Content-Disposition"), "attachment; filename=", "", -1)
fmt.Println("name", name)
file, _ := os.Create(name)
defer file.Close()
io.Copy(file, resp.Body)

@suntong
Copy link
Contributor Author

suntong commented Jul 29, 2021

Love it bro. thx a lot!

@suntong
Copy link
Contributor Author

suntong commented Jul 29, 2021

I'll look into whether we can wrap up everything inside openwechat, instead of pushing all above to the client side...

@suntong
Copy link
Contributor Author

suntong commented Jul 29, 2021

collecting how to use http.DetectContentType:

//判断文件协议content-type,0表示xml,1表示
//alter:    ,by:   ,time:  ,#第几次修改
func DecideFile(body []byte) int {
	if http.DetectContentType(body) == "text/xml; charset=utf-8" {
		return 0
	} else if http.DetectContentType(body) == "text/plain; charset=utf-8" {
		return 1
	}
	return 3
}

func IsPDFFile(data []byte) (string, bool) {
	contentType := http.DetectContentType(data)
	if strings.Index(contentType, "application/pdf") != -1 {
		return contentType, true
	}
	return contentType, false
}

and with Headers["Content-Encoding"]

func (r *ResponseDetails) ConvertToResponseDetailsView() views.ResponseDetailsView {
	needsEncoding := false

	// Check headers for gzip
	contentEncodingValues := r.Headers["Content-Encoding"]
	if len(contentEncodingValues) > 0 {
		needsEncoding = true
	} else {
		mimeType := http.DetectContentType([]byte(r.Body))
		needsEncoding = true
		for _, v := range supportedMimeTypes {
			if strings.Contains(mimeType, v) {
				needsEncoding = false
				break
			}
		}
	}

	// If contains gzip, base64 encode
	body := r.Body
	if needsEncoding {
		body = base64.StdEncoding.EncodeToString([]byte(r.Body))
	}

	return views.ResponseDetailsView{Status: r.Status, Body: body, Headers: r.Headers, EncodedBody: needsEncoding}
}

and just in case need to further parse the ContentType, e.g., video/mp4, application/pdf etc --

@eatmoreapple
Copy link
Owner

Media类型的文件可以直接用msg.FileName拿到文件名称

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants