func (r *request) WithFormDataFileFromReader(key string, name string, reader io.Reader) Request {
	if reader == nil {
		return r.withFormData(key, nil)
	}
	return r.withFormData(key, &formDataValue{file: &formDataFileReader{name: name, reader: reader}})
}
WithFormDataFileFromReader adds an upload target to the current request from
the given reader and file name.
If the given reader is nil, delete the corresponding form key.
package requester
import (
	"bytes"
	"context"
	"encoding"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"
	"github.com/edoger/zkits-requester/internal"
)
var (
	ErrEmptyRequestURL = errors.New("empty request url")
	ErrInvalidRequestBody = errors.New("invalid request body")
	ErrEmptyUploadBody = errors.New("empty upload body")
	ErrInvalidUploadBody = errors.New("invalid upload body")
)
type Request interface {
	WithMethod(string) Request
	WithResponder(Responder) Request
	WithHeader(string, string) Request
	WithHeaderValue(string, interface{}) Request
	WithContentType(string) Request
	WithHeaders(http.Header) Request
	WithContext(context.Context) Request
	WithQuery(string, string) Request
	WithQueryValue(string, interface{}) Request
	WithQueries(url.Values) Request
	WithTimeout(time.Duration) Request
	WithBody(interface{}) Request
	WithJSONBody(interface{}) Request
	WithRawJSONBody([]byte) Request
	WithXMLBody(interface{}) Request
	WithRawXMLBody([]byte) Request
	WithFormBody(url.Values) Request
	WithFormBodyMap(body map[string]interface{}) Request
	Head() (Response, error)
	Get() (Response, error)
	Post() (Response, error)
	Send() (Response, error)
	SendBy(string) (Response, error)
	WithFormDataField(string, interface{}) Request
	WithFormDataFields(fields map[string]interface{}) Request
	WithFormDataFile(string, interface{}) Request
	WithFormDataFileFromReader(string, string, io.Reader) Request
	ClearFormData() Request
	Upload() (Response, error)
	UploadBy(string) (Response, error)
	Clear() Request
}
type request struct {
	client       *client
	uri          string
	method       string
	headers      http.Header
	ctx          context.Context
	query        url.Values
	timeout      time.Duration
	responder    Responder
	body         interface{}
	bodyFormData map[string][]*formDataValue
	bodyEncoder  string
	bodyType     string
}
type formDataValue struct {
	field string
	file  interface{}
}
func (r *request) WithMethod(method string) Request {
	r.method = method
	return r
}
func (r *request) WithResponder(responder Responder) Request {
	r.responder = responder
	return r
}
func (r *request) WithHeader(key, value string) Request {
	if value == "" {
		if len(r.headers) > 0 {
			r.headers.Del(key)
		}
		return r
	}
	if r.headers == nil {
		r.headers = make(http.Header, 1)
	}
	r.headers.Set(key, value)
	return r
}
func (r *request) WithHeaderValue(key string, value interface{}) Request {
	return r.WithHeader(key, internal.ToString(value))
}
func (r *request) WithContentType(ct string) Request {
	r.WithHeader("Content-Type", ct)
	return r
}
func (r *request) WithHeaders(headers http.Header) Request {
	r.headers = headers
	return r
}
func (r *request) WithContext(ctx context.Context) Request {
	r.ctx = ctx
	return r
}
func (r *request) WithQuery(key, value string) Request {
	if r.query == nil {
		r.query = make(url.Values, 1)
	}
	r.query.Set(key, value)
	return r
}
func (r *request) WithQueryValue(key string, value interface{}) Request {
	return r.WithQuery(key, internal.ToString(value))
}
func (r *request) WithQueries(qs url.Values) Request {
	r.query = qs
	return r
}
func (r *request) WithTimeout(t time.Duration) Request {
	r.timeout = t
	return r
}
func (r *request) WithBody(body interface{}) Request {
	r.body = body
	r.bodyEncoder = ""
	r.bodyType = ""
	return r
}
func (r *request) WithJSONBody(body interface{}) Request {
	r.body = body
	r.bodyEncoder = "json"
	r.bodyType = "application/json"
	return r
}
func (r *request) WithRawJSONBody(body []byte) Request {
	r.body = body
	r.bodyEncoder = ""
	r.bodyType = "application/json"
	return r
}
func (r *request) WithXMLBody(body interface{}) Request {
	r.body = body
	r.bodyEncoder = "xml"
	r.bodyType = "application/xml"
	return r
}
func (r *request) WithRawXMLBody(body []byte) Request {
	r.body = body
	r.bodyEncoder = ""
	r.bodyType = "application/xml"
	return r
}
func (r *request) WithFormBody(body url.Values) Request {
	r.body = body
	r.bodyEncoder = ""
	r.bodyType = "application/x-www-form-urlencoded"
	return r
}
func (r *request) WithFormBodyMap(body map[string]interface{}) Request {
	values := make(url.Values, len(body))
	for key, value := range body {
		values.Set(key, internal.ToString(value))
	}
	return r.WithFormBody(values)
}
func (r *request) Head() (Response, error) {
	return r.SendBy(http.MethodHead)
}
func (r *request) Get() (Response, error) {
	return r.SendBy(http.MethodGet)
}
func (r *request) Post() (Response, error) {
	return r.SendBy(http.MethodPost)
}
func (r *request) Send() (Response, error) {
	return r.SendBy(r.method)
}
func (r *request) SendBy(method string) (Response, error) {
	if r.uri == "" {
		return nil, ErrEmptyRequestURL
	}
	if o, err := r.send(strings.ToUpper(method)); err != nil {
		return nil, err
	} else {
		return r.fromResponder(o, o.Request.Method == http.MethodHead)
	}
}
func (r *request) fromResponder(o *http.Response, noBody bool) (Response, error) {
	if r.responder != nil {
		return r.responder(o, noBody)
	}
	if r.client.responder != nil {
		return r.client.responder(o, noBody)
	}
	return NewResponse(o, noBody)
}
func (r *request) send(method string) (*http.Response, error) {
	body, err := r.makeBodyReader()
	if err != nil {
		return nil, err
	}
	ctx, cancel := r.getContext()
	if cancel != nil {
		defer cancel()
	}
	req, err := http.NewRequestWithContext(ctx, method, r.uri, body)
	if err != nil {
		return nil, err
	}
	if len(r.client.headers) > 0 {
		for key, values := range r.client.headers {
			req.Header[key] = values
		}
	}
	if len(r.headers) > 0 {
		for key, values := range r.headers {
			req.Header[key] = values
		}
	}
	if r.bodyType != "" {
		req.Header.Set("Content-Type", r.bodyType)
	}
	if len(r.query) > 0 {
		if req.URL.RawQuery == "" {
			req.URL.RawQuery = r.query.Encode()
		} else {
			qs := req.URL.Query()
			for key, values := range r.query {
				qs[key] = values
			}
			req.URL.RawQuery = qs.Encode()
		}
	}
	if r.client.http == nil {
		return internal.Client.Do(req)
	} else {
		return r.client.http.Do(req)
	}
}
func (r *request) getContext() (context.Context, context.CancelFunc) {
	ctx := r.ctx
	if ctx == nil {
		ctx = context.Background()
	}
	if r.timeout > 0 {
		return context.WithTimeout(ctx, r.timeout)
	}
	if r.client.timeout > 0 {
		return context.WithTimeout(ctx, r.client.timeout)
	}
	return ctx, nil
}
func (r *request) makeBodyReader() (io.Reader, error) {
	if r.body == nil {
		return nil, nil
	}
	if r.bodyEncoder != "" {
		switch r.bodyEncoder {
		case "json":
			if data, err := json.Marshal(r.body); err != nil {
				return nil, err
			} else {
				return bytes.NewReader(data), nil
			}
		case "xml":
			if data, err := xml.Marshal(r.body); err != nil {
				return nil, err
			} else {
				return bytes.NewReader(data), nil
			}
		}
	}
	switch body := r.body.(type) {
	case string:
		return strings.NewReader(body), nil
	case []byte:
		return bytes.NewReader(body), nil
	case url.Values:
		return strings.NewReader(body.Encode()), nil
	case io.Reader:
		return body, nil
	case fmt.Stringer:
		return strings.NewReader(body.String()), nil
	case encoding.TextMarshaler:
		if data, err := body.MarshalText(); err != nil {
			return nil, err
		} else {
			return bytes.NewReader(data), nil
		}
	}
	return nil, ErrInvalidRequestBody
}
func (r *request) WithFormDataField(key string, value interface{}) Request {
	if value == nil {
		return r.withFormData(key, nil)
	}
	return r.withFormData(key, &formDataValue{field: internal.ToString(value)})
}
func (r *request) WithFormDataFields(fields map[string]interface{}) Request {
	for key, value := range fields {
		r.WithFormDataField(key, value)
	}
	return r
}
func (r *request) WithFormDataFile(key string, value interface{}) Request {
	if value == nil {
		return r.withFormData(key, nil)
	}
	return r.withFormData(key, &formDataValue{file: value})
}
type formDataFileReader struct {
	name   string
	reader io.Reader
}