Supports AutoConnectFile

pull/57/head
Hieromon Ikasamo 6 years ago
parent a987caf498
commit 4b3167263d
  1. 6
      mkdocs/acelements.md
  2. 44
      mkdocs/acupload.md
  3. 7
      src/AutoConnectAux.h
  4. 2
      src/AutoConnectUpload.h
  5. 8
      src/AutoConnectUploadImpl.h

@ -194,9 +194,9 @@ A `label` is an optional string. A label is always arranged on the left side of
Specifies the destination to save the uploaded file. The destination can be specified the following values in the *ACFile_t* enumeration type. Specifies the destination to save the uploaded file. The destination can be specified the following values in the *ACFile_t* enumeration type.
- AC_File_FS: Save as the SPIFFS file in flash of ESP8266/ESP32 module. - **`AC_File_FS`** : Save as the SPIFFS file in flash of ESP8266/ESP32 module.
- AC_File_SD: Save to an external SD device connected to ESP8266/ESP32 module. - **`AC_File_SD`** : Save to an external SD device connected to ESP8266/ESP32 module.
- AC_File_Extern: Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit [**AutoConnectUploadHandler**](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) class and implements *_open*, *_write* and *_close* function. - **`AC_File_Extern`** : Pass the content of the uploaded file to the uploader which is declared by the sketch individually. Its uploader must inherit [**AutoConnectUploadHandler**](acupload.md#to-upload-to-a-device-other-than-flash-or-sd) class and implements *_open*, *_write* and *_close* function.
!!! note "Built-in uploader is ready." !!! note "Built-in uploader is ready."
AutoConnect already equips the built-in uploader for saving to the SPIFFS as AC_File_FS and the external SD as AC_File_SD. It is already implemented inside AutoConnect and will store uploaded file automatically. AutoConnect already equips the built-in uploader for saving to the SPIFFS as AC_File_FS and the external SD as AC_File_SD. It is already implemented inside AutoConnect and will store uploaded file automatically.

@ -149,19 +149,21 @@ Also, the substance of AC_File_SD (sd) is a FAT file of Arduino SD library porte
## When it will be uploaded ## When it will be uploaded
The below diagram shows the file uploading sequence. Upload handler will be launched by ESP8266WebServer/WebServer(ESP32) library which is triggered by receiving an HTTP stream of POST BODY including file content. Its launching occurs before invoking the page handler. Upload handler will be launched by ESP8266WebServer/WebServer(ESP32) library which is triggered by receiving an HTTP stream of POST BODY including file content. Its launching occurs before invoking the page handler.
At the time of the page handler behaves, the uploaded file already saved to the device, and the [member variables](acelements.md#name_3) of AutoConnectFile reflects the file name and transfer size. The following diagram illustrates the file uploading sequence:
<img src="images/ac_upload_flow.svg"> <img src="images/ac_upload_flow.svg">
At the time of the page handler behaves, the uploaded file already saved to the device, and the [member variables](acelements.md#name_3) of AutoConnectFile reflects the file name and transfer size.
## The file name for the uploaded file ## The file name for the uploaded file
AutoConnetFile saves the uploaded file with the file name you selected by `<input type="file">` tag on the browser. The file name used for uploading is stored in the AutoConnetFile's value member, which you can access after uploading. (i.e. In the handler of the destination page by the AutoConnectSubmit element.) You can not save it with a different name. It can be renamed after upload if you need to change the name. AutoConnetFile saves the uploaded file with the file name you selected by `<input type="file">` tag on the browser. The file name used for uploading is stored in the AutoConnetFile's value member, which you can access after uploading. (i.e. In the handler of the destination page by the AutoConnectSubmit element.) You can not save it with a different name. It can be renamed after upload if you need to change the name.
## To upload to a device other than Flash or SD ## Upload to a device other than Flash or SD
You can output the file to any device using a custom uploader by specifying [**extern**](acjson.md#acfile) with the [store](acjson.md#acfile) attribute of AutoConnectFile (or specifying [**AC_File_Extern**](acelements.md#store) for the store member variable) and can customize the uploader according to the need to upload files to other than Flash or SD. Implements your own uploader with inheriting the [**AutoConnectUploadHandler**](#upload-handler-base-class) class which is the base class of the upload handler. You can output the file to any device using a custom uploader by specifying [**extern**](acjson.md#acfile) with the [store](acjson.md#acfile) attribute of [AutoConnectFile (or specifying [**AC_File_Extern**](acelements.md#store) for the store member variable) and can customize the uploader according to the need to upload files to other than Flash or SD. Implements your own uploader with inheriting the [**AutoConnectUploadHandler**](#upload-handler-base-class) class which is the base class of the upload handler.
!!! note "It's not so difficult" !!! note "It's not so difficult"
Implementing the custom uploader requires a little knowledge of the c++ language. If you are less attuned to programming c++, you may find it difficult. But don't worry. You can make it in various situations by just modifying the sketch skeleton that appears at the end of this page. Implementing the custom uploader requires a little knowledge of the c++ language. If you are less attuned to programming c++, you may find it difficult. But don't worry. You can make it in various situations by just modifying the sketch skeleton that appears at the end of this page.
@ -205,17 +207,17 @@ typedef struct {
</span></dd> </span></dd>
</dl> </dl>
The upload handler needs to implement processing based on the enumeration value of HTTPUpload.status HTTPUploadStatus enum type. HTTPUploadStatus enumeration is as follows: The upload handler needs to implement processing based on the enumeration value of HTTPUpload.status as **HTTPUploadStatus** enum type. HTTPUploadStatus enumeration is as follows:
- UPLOAD_FILE_START: Invokes to the \_open. - **`UPLOAD_FILE_START`** : Invokes to the \_open.
- UPLOAD_FILE_WRITE: Invokes to the \_write. - **`UPLOAD_FILE_WRITE`** : Invokes to the \_write.
- UPLOAD_FILE_END: Invokes to the \_close. - **`UPLOAD_FILE_END`** : Invokes to the \_close.
- UPLOAD_FILE_ABORTED: Invokes to the \_close. - **`UPLOAD_FILE_ABORTED`** : Invokes to the \_close.
```cpp ```cpp
protected virtual bool _open(const char* filename, const char* mode) = 0 protected virtual bool _open(const char* filename, const char* mode) = 0
``` ```
The \_open function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_START**. Usually, the implementation of an inherited class will usually open the file. The \_open function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_START**. Usually, the implementation of an inherited class will open the file.
<dl class="apidl"> <dl class="apidl">
<dt>**Parameters**</dt> <dt>**Parameters**</dt>
<dd><span class="apidef">filename</span><span class="apidesc">Uploading file name.</span></dd> <dd><span class="apidef">filename</span><span class="apidesc">Uploading file name.</span></dd>
@ -226,7 +228,7 @@ The \_open function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_START
</dl> </dl>
```cpp ```cpp
protected virtual size_t _write(const uint8_t *buf, size_t size))= 0 protected virtual size_t _write(const uint8_t *buf, const size_t size))= 0
``` ```
The \_write function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_WRITE**. The content of the upload file is divided and the \_write will be invoked in multiple times. Usually, the implementation of an inherited class will write data. The \_write function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_WRITE**. The content of the upload file is divided and the \_write will be invoked in multiple times. Usually, the implementation of an inherited class will write data.
<dl class="apidl"> <dl class="apidl">
@ -242,7 +244,7 @@ protected virtual void _close(void) = 0
``` ```
The \_close function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_END** or **UPLOAD_FILE_ABORTED**. Usually, the implementation of an inherited class will close the file. The \_close function will be invoked when HTTPUploadStatus is **UPLOAD_FILE_END** or **UPLOAD_FILE_ABORTED**. Usually, the implementation of an inherited class will close the file.
For reference, the following AutoConnectUploadFS class is AutoConnect built-in uploader. This class implementation also inherits from AutoConnectUploadHandler. For reference, the following AutoConnectUploadFS class is an implementation of AutoConnect built-in uploader and inherits from AutoConnectUploadHandler.
```cpp ```cpp
class AutoConnectUploadFS : public AutoConnectUploadHandler { class AutoConnectUploadFS : public AutoConnectUploadHandler {
@ -259,7 +261,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler {
return false; return false;
} }
size_t _write(const uint8_t* buf, size_t size) override { size_t _write(const uint8_t* buf, const size_t size) override {
if (_file) if (_file)
return _file.write(buf, size); return _file.write(buf, size);
else else
@ -272,6 +274,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler {
_media->end(); _media->end();
} }
private:
SPIFFST* _media; SPIFFST* _media;
SPIFileT _file; SPIFileT _file;
}; };
@ -281,6 +284,15 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler {
In order to upload a file by the custom uploader, it is necessary to register it to the custom Web page beforehand. To register a custom uploader, specify the custom uploader class name in the template argument of the [AutoConnectAux::onUpload](apiaux.md#onupload) function and invokes it. In order to upload a file by the custom uploader, it is necessary to register it to the custom Web page beforehand. To register a custom uploader, specify the custom uploader class name in the template argument of the [AutoConnectAux::onUpload](apiaux.md#onupload) function and invokes it.
```cpp
void AutoConnectAux::onUpload<T>(T& uploadClass)
```
<dl class="apidl">
<dt>**Parameters**</dt>
<dd><span class="apidef">T</span><span class="apidesc">Specifies a class name of the custom uploader. This class name is a class that you implemented by inheriting AutoConnectUploadHandler for custom upload.</span></dd>
<dd><span class="apidef">uploadClass</span><span class="apidesc">Specifies the custom upload class instance.</span></dd>
</dl>
The rough structure of the sketches that completed these implementations will be as follows: The rough structure of the sketches that completed these implementations will be as follows:
```cpp ```cpp
@ -320,17 +332,17 @@ public:
protected: protected:
bool _open(const char* filename, const char* mode) override; bool _open(const char* filename, const char* mode) override;
size_t _write(const uint8_t *buf, size_t size) override; size_t _write(const uint8_t *buf, const size_t size) override;
void _close(void) override; void _close(void) override;
}; };
// _open for custom open // _open for custom open
bool CustomUploader::_open(const char* filename, const char* mode) { bool CustomUploader::_open(const char* filename, const char* mode) {
// Here, an implementation for the open file. // Here, an implementation for the open file.
}) }
// _open for custom write // _open for custom write
size_t CustomUploader::_write(const uint8_t *buf, size_t size) { size_t CustomUploader::_write(const uint8_t *buf, const size_t size) {
// Here, an implementation for the writing the file data. // Here, an implementation for the writing the file data.
} }

@ -14,6 +14,7 @@
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <type_traits>
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
#include <Stream.h> #include <Stream.h>
#endif // !AUTOCONNECT_USE_JSON #endif // !AUTOCONNECT_USE_JSON
@ -63,8 +64,10 @@ class AutoConnectAux : public PageBuilder {
void setTitle(const String& title) { _title = title; } /**< Set a title of the auxiliary page */ void setTitle(const String& title) { _title = title; } /**< Set a title of the auxiliary page */
void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */ void on(const AuxHandlerFunctionT handler, const AutoConnectExitOrder_t order = AC_EXIT_AHEAD) { _handler = handler; _order = order; } /**< Set user handler */
void onUpload(PageBuilder::UploadFuncT uploadFunc) override { _uploadHandler = uploadFunc; } void onUpload(PageBuilder::UploadFuncT uploadFunc) override { _uploadHandler = uploadFunc; }
template<typename T> template<typename T, typename = typename std::enable_if<std::is_base_of<AutoConnectUploadHandler, T>::value>::type>
void onUpload(T& uploadClass) { _uploadHandler = std::bind(&T::upload, &uploadClass, std::placeholders::_1, std::placeholders::_2); } void onUpload(T& uploadClass) {
_uploadHandler = std::bind(&T::upload, &uploadClass, std::placeholders::_1, std::placeholders::_2);
}
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */ bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */

@ -31,7 +31,7 @@ class AutoConnectUploadHandler {
protected: protected:
virtual bool _open(const char* filename, const char* mode) = 0; virtual bool _open(const char* filename, const char* mode) = 0;
virtual size_t _write(const uint8_t *buf, size_t size) = 0; virtual size_t _write(const uint8_t *buf, const size_t size) = 0;
virtual void _close(void) = 0; virtual void _close(void) = 0;
}; };

@ -55,7 +55,7 @@ void AutoConnectUploadHandler::upload(const String& requestUri, const HTTPUpload
break; break;
} }
case UPLOAD_FILE_WRITE: case UPLOAD_FILE_WRITE:
(void)_write(upload.buf, upload.currentSize); (void)_write(upload.buf, (const size_t)upload.currentSize);
break; break;
case UPLOAD_FILE_ABORTED: case UPLOAD_FILE_ABORTED:
case UPLOAD_FILE_END: case UPLOAD_FILE_END:
@ -83,7 +83,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler {
return false; return false;
} }
size_t _write(const uint8_t* buf, size_t size) override { size_t _write(const uint8_t* buf, const size_t size) override {
if (_file) if (_file)
return _file.write(buf, size); return _file.write(buf, size);
else else
@ -96,6 +96,7 @@ class AutoConnectUploadFS : public AutoConnectUploadHandler {
_media->end(); _media->end();
} }
private:
SPIFFST* _media; SPIFFST* _media;
SPIFileT _file; SPIFileT _file;
}; };
@ -121,7 +122,7 @@ class AutoConnectUploadSD : public AutoConnectUploadHandler {
return false; return false;
} }
size_t _write(const uint8_t* buf, size_t size) override { size_t _write(const uint8_t* buf, const size_t size) override {
if (_file) if (_file)
return _file.write(buf, size); return _file.write(buf, size);
else else
@ -134,6 +135,7 @@ class AutoConnectUploadSD : public AutoConnectUploadHandler {
_media->end(); _media->end();
} }
private:
SDClassT* _media; SDClassT* _media;
SDFileT _file; SDFileT _file;
uint8_t _cs; uint8_t _cs;

Loading…
Cancel
Save