-
Notifications
You must be signed in to change notification settings - Fork 17.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: mime/multipart: add WriteFile method to mime/multipart.Writer for streamlined file uploads from io.Reader #65096
Comments
@bradfitz @ianlancetaylor |
This comment was marked as spam.
This comment was marked as spam.
Thanks. It would help to point to some existing code that would benefit from this method. |
Is this just to save 4 lines of code? |
@ianlancetaylor Example 1: HTTP Handler http.HandleFunc("/upload-profile-picture", func(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20) // 10 MB limit
file, header, err := r.FormFile("profilePicture")
if err != nil {
fmt.Fprintf(w, "File upload error: %v", err)
return
}
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
part, err := writer.CreateFormFile("profilePicture", header.Filename)
if err != nil {
fmt.Fprintf(w, "Error creating form file: %v", err)
return
}
_, err = io.Copy(part, file)
if err != nil {
fmt.Fprintf(w, "Error copying file: %v", err)
return
}
// Further processing...
}) Improved approach with http.HandleFunc("/upload-profile-picture", func(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20) // 10 MB limit
file, header, err := r.FormFile("profilePicture")
if err != nil {
fmt.Fprintf(w, "File upload error: %v", err)
return
}
defer file.Close()
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
if err := writer.WriteFile("profilePicture", header.Filename, file); err != nil {
fmt.Fprintf(w, "Error writing file: %v", err)
return
}
// Further processing...
}) Example 2: Batch Processing of Uploads Current approach without var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
for _, file := range files { // Assuming 'files' is a slice of file streams
part, err := writer.CreateFormFile("file", file.Name)
if err != nil {
log.Fatal(err)
}
_, err = io.Copy(part, file.Stream)
if err != nil {
log.Fatal(err)
}
}
writer.Close()
// Buffer now contains all the files in multipart form, ready for batch upload. Improved approach with var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
for _, file := range files { // Assuming 'files' is a slice of file streams with Name and Stream properties
err := writer.WriteFile("file", file.Name, file.Stream)
if err != nil {
log.Fatal(err)
}
}
writer.Close()
// The process is simplified, focusing on what matters: preparing the files for upload. As you see the |
Thank you for your comment. On the surface, the addition of the Error Handling: Centralizing the file-writing process into a single method allows for more consistent and potentially sophisticated error handling(just like in my examples abve). It reduces the risk of common mistakes made during manual copying and error checks. Consistency and Readability: The proposal also hinges on creating an API that is consistent and easy-to-understand. Having a |
Proposal Details
Abstract
This proposal suggests adding a new method,
WriteFile
, to themime/multipart.Writer
type in the Go standard library. TheWriteFile
method will simplify the process of adding file content to multipart forms directly from anio.Reader
, enhancing the package's capability to handle file uploads efficiently, especially for large files or files sourced from streams.Background
The current
mime/multipart.Writer
API provides methods likeCreateFormFile
andCreateFormField
for adding files and fields to multipart forms, which are widely used in HTTP client and server implementations for file uploads. However, after callingCreateFormFile
, developers must manually copy the file content into the returned writer, which can be cumbersome.Proposal
I propose adding a new method to the
mime/multipart.Writer
type:This method will perform the following tasks:
Rationale
Ease of Use: The WriteFile method abstracts away the boilerplate code associated with setting up form file parts and copying data, leading to cleaner and more concise client code.
Efficiency: It's particularly beneficial for streaming large files or data from network sources, as it doesn't require loading the entire file content into memory.
Consistency with Existing APIs: While the
mime/multipart
package already providesWriteField
for simple text fields, there is no equivalent convenience method for files.WriteFile
fills this gap and aligns with the existing API design.Compatibility
This change is fully backward-compatible. It introduces a new method to the existing mime/multipart.Writer type without modifying any existing functionality. It will not affect existing codebases using the mime/multipart package.
Conclusion
Adding
WriteFile
to mime/multipart.Writer will enhance the Go standard library's ability to handle file uploads in a more efficient and user-friendly manner. This addition is a natural extension of the existing multipart API and will be beneficial for a wide range of applications that rely on file uploads, particularly those dealing with large or streamed files.The text was updated successfully, but these errors were encountered: