使用GoLang转换curl多部分请求时遇文件扩展名错误求助
Fixing "File extension not allowed" Error in Documo Fax API Go Implementation
Let's break down why you're hitting that error even with a valid PDF file, and fix your code step by step.
Root Causes of the Error
- Redundant & Broken File Handling: Your original code reads the entire file into memory first, which moves the file pointer to the end—so the subsequent
io.Copydoes nothing. Plus, manually writing the file content as a string introduces unnecessary overhead and potential corruption risks. - Mismatched Form Field Name: Your curl command uses an empty string as the file field name (
-F '=@/path/to/file'), but your Go code uses"file"instead. Documo's API likely can't recognize the file when the field name doesn't match what it expects. - Incorrect Authorization Header Format: Basic auth requires your API key to be base64-encoded as
apiKey:(with an empty password), but your code uses a raw key directly.
Corrected Code
First, update the SendMultipartRequest function to fix these issues:
import ( "bytes" "encoding/base64" "fmt" "io" "net/http" "net/http/httputil" "net/textproto" ) func SendMultipartRequest(uri string, params map[string]string, files []*multipart.FileHeader, apiKey string) (*http.Request, error) { body := &bytes.Buffer{} writer := multipart.NewWriter(body) // Process files: use empty string as field name to match curl for _, fh := range files { file, err := fh.Open() if err != nil { return nil, fmt.Errorf("failed to open file %s: %w", fh.Filename, err) } defer file.Close() // Create form field with empty name (matches curl's `-F '=@file'` syntax) part, err := writer.CreateFormFile("", fh.Filename) if err != nil { return nil, fmt.Errorf("failed to create form entry for %s: %w", fh.Filename, err) } // Efficiently copy file content without reading entire file into memory if _, err := io.Copy(part, file); err != nil { return nil, fmt.Errorf("failed to copy content from %s: %w", fh.Filename, err) } } // Add form parameters for key, val := range params { if err := writer.WriteField(key, val); err != nil { return nil, fmt.Errorf("failed to write field %s: %w", key, err) } } // Close the writer to finalize the multipart boundary if err := writer.Close(); err != nil { return nil, fmt.Errorf("failed to close multipart writer: %w", err) } // Create the POST request req, err := http.NewRequest(http.MethodPost, uri, body) if err != nil { return nil, fmt.Errorf("failed to construct request: %w", err) } // Set correct content type for multipart form data req.Header.Set("Content-Type", writer.FormDataContentType()) // Encode API key for Basic Authorization authEncoded := base64.StdEncoding.EncodeToString([]byte(apiKey + ":")) req.Header.Set("Authorization", "Basic "+authEncoded) return req, nil }
Then update the SendFaxDocumo function with proper error handling and cleanup:
func SendFaxDocumo(files []*multipart.FileHeader, params map[string]string, apiKey string) { req, err := SendMultipartRequest("https://api.documo.com/v1/fax/send", params, files, apiKey) if err != nil { fmt.Printf("Request setup failed: %v\n", err) return } client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("Request failed to send: %v\n", err) return } // Ensure response body is closed to prevent resource leaks defer resp.Body.Close() // Read response body respBody, err := io.ReadAll(resp.Body) if err != nil { fmt.Printf("Failed to read response: %v\n", err) return } // Print response details for debugging fmt.Printf("Status Code: %d\n", resp.StatusCode) fmt.Printf("Response Headers:\n%v\n", resp.Header) fmt.Printf("Response Body:\n%s\n", string(respBody)) }
How to Use the Corrected Code
Here's an example of calling the function with your parameters:
func main() { // Assume you have your files ready (e.g., from an HTTP form upload) // For testing, you could construct a multipart.FileHeader manually, or use form data params := map[string]string{ "recipientFax": "12345678900", "coverPage": "false", "recipientName": "John", "subject": "test", "notes": "test", } yourApiKey := "YOUR_ACTUAL_DOCUMO_API_KEY" // Replace `files` with your actual file list SendFaxDocumo(files, params, yourApiKey) }
Key Fixes Explained
- File Handling: We use
io.Copydirectly to stream the file content to the multipart writer, avoiding unnecessary memory usage and file pointer issues. - Field Name Match: Using an empty string for the file field name aligns with your original curl command, ensuring Documo's API recognizes the uploaded file.
- Proper Auth: We correctly encode the API key for Basic Authorization, which is required by Documo's API (even if your original error wasn't auth-related, this prevents future issues).
- Robust Error Handling: Every error is wrapped with context and returned immediately, preventing invalid execution flow.
内容的提问来源于stack exchange,提问作者Anam Shah
相关产品推荐
相关产品推荐

