Fastapi simply implements temporary download links

My WeChat official account provides a file download function, which is a file InstMsiW.exe that is required when wine installs WeChat. Last time, the path was hard-coded and placed in the static directory. The user obtained the link to download through the public account conversation, and the link was always valid.

There will be a problem in this. The bandwidth of my personal website is limited, and I don’t want to put it on CDN. I have to find a way to generate a temporary file download link, which will be valid for a period of time and expire after a period of time. It not only serves real fans, but also saves money. Cost, life is hard enough these days, we can’t do loss-making business, we don’t have the strength yet.

The implementation process is recorded below:

1. Use itsdangerous library’s URLSafeTimedSerializer to implement temporary tokens

Directly enter the code without tediousness

 1# Note that the new version of itsdangerous is URLSafeTimedSerializer
 2from itsdangerous import URLSafeTimedSerializer as Serializer
 3from itsdangerous import BadSignature, SignatureExpired
 4from fastapi.responses import FileResponse
 5
 6@app.get("/api/get_file/{token}") # token is passed through path parameter
 7async def get_file(token):
 8     s = Serializer("your secret key") # Your key, you should know, the token I developed directly using the public account
 9     try:
10         # max_age = 60 * 10 The identification token is valid within ten minutes. If it exceeds, SignatureExpired will be triggered, which is very important! ! !
11         to_user = s.loads(token, max_age=60 * 10)["to_user"]
12     except SignatureExpired:
13         logger.info("Token timed out, verification failed")
14         return {"status": "fail", "data": "expired token(token timeout, verification failed)"} # Information is provided in both Chinese and English, with good intentions😄, there may be readers who are not good at English
15     except BadSignature:
16         logger.info("Invalid token")
17         return {"status": "fail", "data": "bad token(invalid token)"}
18     print("to_user", to_user)
19     # The front is the path of the file to be downloaded, and the back is the file name after next week. filename is very important, otherwise it will not be friendly enough. If you don’t believe me, try removing it.
20     # Currently only one file is provided for download, so it is hard-coded.
21     return FileResponse("api/downloads/InstMsiW.exe", filename="InstMsiW.exe")

Note that the token is in the URL request parameter. Generally speaking, the characters that can be legally used in the URL are limited, so it is called URLSafeTimedSerializer. When URLSafeTimedSerializer loads, the aging can be controlled through max_age.

Why does it work? Check the source code to see:

why max age work

I have to say that this is really convenient and easy to use. It seems that the activation email of the registration service has a similar principle. It's just that here I return the download link directly, and the activation service is to continue processing business-related information.

 1### Omit 10,000 lines of code here ###
 2# It means that if the public account user sends "Open Sesame", a temporary download address will be replied to the user.
 3if Content == "Open Sesame":
 4     s = Serializer("your secret key") # Your key, you should know, the token I developed directly using the public account
 5     token = s.dumps({"to_user": toUser}) # Generally, a unique token is used for dumps. Dumps can be simply understood as encryption, and loads are analogous to decryption.
 6     logger.info("Start sending download link")
 7     print("token:", token)
 8     content = f"InstMsiw temporary download address (please use a browser to open it, the download link will be valid within 10 minutes): https://stock.mephisto.cc/api/get_file/{token}"
 9     replyMsg = reply.TextMsg(toUser, fromUser, content)
10     return replyMsg.send()

2. Various examples

It is said that there is a picture and there is a truth. If it is correct, send "Open Sesame" and return to a different download address. The link will be valid for ten minutes. There should be no one who is so bored and keeps browsing this.

temporary download

If it exceeds 10 minutes, a timeout will be prompted, which is consistent with expectations.

download expired

Delete 4 characters to simulate testing the wrong token situation, and it works normally.

bad token

3. Conclusion

The function of temporary download links is quite interesting. Of course, you can also limit the number of downloads. Actor Huang Bo said: "I don't think this is necessary! Beware of gentlemen, not villains."

The above is my own practice and exploration based on various information on the Internet. Programming experts may have easier methods.

I am not an expert, and the only thing I can achieve at present is this. It can solve the real problems encountered, and I hope it will be helpful to readers.

Lastmod: Tuesday, January 30, 2024

See Also:

Translations: