-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAsyncSDFileResponse.cpp
133 lines (111 loc) · 4.34 KB
/
AsyncSDFileResponse.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Serve files using SdFat
// Modified from https://gist.github.com/pim-borst
#include <Arduino.h>
#include <SPI.h>
#include "SdFat.h"
#define FS_NO_GLOBALS
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
class AsyncSDFileResponse: public AsyncAbstractResponse {
private:
File _content;
String _path;
void _setContentType(const String& path);
bool _sourceIsValid;
bool SD_exists(SdFat &sd, String path);
public:
AsyncSDFileResponse(SdFat &sd, const String& path, const String& contentType=String(), bool download=false);
AsyncSDFileResponse(File content, const String& path, const String& contentType=String(), bool download=false);
~AsyncSDFileResponse();
bool _sourceValid() const { return _sourceIsValid; }
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
};
AsyncSDFileResponse::~AsyncSDFileResponse(){
if(_content)
_content.close();
}
void AsyncSDFileResponse::_setContentType(const String& path){
if (path.endsWith(".html")) _contentType = "text/html";
else if (path.endsWith(".htm")) _contentType = "text/html";
else if (path.endsWith(".css")) _contentType = "text/css";
else if (path.endsWith(".csv")) _contentType = "text/csv";
else if (path.endsWith(".json")) _contentType = "text/json";
else if (path.endsWith(".js")) _contentType = "application/javascript";
else if (path.endsWith(".png")) _contentType = "image/png";
else if (path.endsWith(".gif")) _contentType = "image/gif";
else if (path.endsWith(".jpg")) _contentType = "image/jpeg";
else if (path.endsWith(".ico")) _contentType = "image/x-icon";
else if (path.endsWith(".svg")) _contentType = "image/svg+xml";
else if (path.endsWith(".eot")) _contentType = "font/eot";
else if (path.endsWith(".woff")) _contentType = "font/woff";
else if (path.endsWith(".woff2")) _contentType = "font/woff2";
else if (path.endsWith(".ttf")) _contentType = "font/ttf";
else if (path.endsWith(".txt")) _contentType = "text/plain";
else if (path.endsWith(".xml")) _contentType = "text/xml";
else if (path.endsWith(".pdf")) _contentType = "application/pdf";
else if (path.endsWith(".zip")) _contentType = "application/zip";
else if(path.endsWith(".gz")) _contentType = "application/x-gzip";
else _contentType = "application/octet-stream";
}
bool AsyncSDFileResponse::SD_exists(SdFat &sd, String path) {
// For some reason SD.exists(filename) reboots the ESP...
// So we test by opening the file
bool exists = false;
File test = sd.open(path);
if(test){
test.close();
exists = true;
}
return exists;
}
AsyncSDFileResponse::AsyncSDFileResponse(SdFat &sd, const String& path, const String& contentType, bool download){
_code = 200;
_path = path;
if(!download && !SD_exists(sd, _path) && SD_exists(sd, _path+".gz")){
_path = _path+".gz";
addHeader("Content-Encoding", "gzip");
}
_content = sd.open(_path, O_READ);
_contentLength = _content.size();
_sourceIsValid = _content;
if(contentType == "")
_setContentType(path);
else
_contentType = contentType;
int filenameStart = path.lastIndexOf('/') + 1;
char buf[26+path.length()-filenameStart];
char* filename = (char*)path.c_str() + filenameStart;
if(download) {
// set filename and force download
snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename);
} else {
// set filename and force rendering
snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename);
}
addHeader("Content-Disposition", buf);
}
AsyncSDFileResponse::AsyncSDFileResponse(File content, const String& path, const String& contentType, bool download){
_code = 200;
_path = path;
_content = content;
_contentLength = _content.size();
if(!download && String(_content.name()).endsWith(".gz") && !path.endsWith(".gz"))
addHeader("Content-Encoding", "gzip");
if(contentType == "")
_setContentType(path);
else
_contentType = contentType;
int filenameStart = path.lastIndexOf('/') + 1;
char buf[26+path.length()-filenameStart];
char* filename = (char*)path.c_str() + filenameStart;
if(download) {
snprintf(buf, sizeof (buf), "attachment; filename=\"%s\"", filename);
} else {
snprintf(buf, sizeof (buf), "inline; filename=\"%s\"", filename);
}
addHeader("Content-Disposition", buf);
}
size_t AsyncSDFileResponse::_fillBuffer(uint8_t *data, size_t len){
_content.read(data, len);
return len;
}