APIs for File Conversion: Examples in Golang


File conversion is an essential feature in many applications, enabling users to transform files between various formats, such as converting images from PNG to JPEG or documents from DOCX to PDF. Automating this process through an API can streamline workflows and integrate seamlessly with other software.
This guide delves into designing, implementing, and using a file conversion API, illustrated with a practical example built in Golang.
Key Features of a File Conversion API
To build a robust file conversion API, it must incorporate the following features:
Format Support: Accept and convert between multiple formats (e.g., PNG to JPEG, TXT to PDF).
Secure Upload and Download: Ensure files are securely uploaded and stored.
Scalability: Handle large files and high-throughput environments efficiently.
Error Handling: Gracefully manage unsupported formats or conversion failures.
Authentication: Restrict access using API keys or tokens.
API Design
A well-designed API simplifies the integration process. Below is a proposed design for the file conversion API.
Method | Endpoint | Description |
POST | /convert | Upload a file and specify conversion parameters. |
GET | /status/{task_id} | Check the status of a specific conversion task. |
GET | /download/{task_id} | Download the converted file. |
Request and Response Examples
Conversion Request (POST /convert)
Request:
{ "input_format": "png", "output_format": "jpg" }
File is sent as
multipart/form-data
.Response:
{ "task_id": "123456", "status": "processing" }
Check Conversion Status (GET /status/{task_id})
Response:
{ "task_id": "123456", "status": "completed", "download_url": "/download/123456" }
Download File (GET /download/{task_id})
Returns the converted file as a response.
Building the API in Golang
To implement the API, Golang offers robust libraries for handling HTTP requests, file uploads, and background tasks. Below is a detailed walkthrough.
Dependencies
This implementation relies on the following libraries:
Mux โ A powerful routing library for handling HTTP requests.
๐ github.com/gorilla/muxos/exec โ Provides functions for executing system commands, useful for file conversion tasks.
๐ pkg.go.dev/os/execio/ioutil โ Used for file handling (โ ๏ธ Deprecated since Go 1.16; use
io
andos
instead).
๐ pkg.go.dev/io/ioutiluuid โ Generates unique task IDs, ensuring reliable identification.
๐ github.com/google/uuid
Install these dependencies:
go get github.com/gorilla/mux
go get github.com/google/uuid
Code Implementation
Here is a simplified implementation:
package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/mux"
"github.com/google/uuid"
"io"
"net/http"
"os"
"os/exec"
"sync"
)
type ConversionTask struct {
TaskID string `json:"task_id"`
InputFormat string `json:"input_format"`
OutputFormat string `json:"output_format"`
Status string `json:"status"`
FilePath string
}
var (
taskStore = sync.Map{}
)
func main() {
r := mux.NewRouter()
r.HandleFunc("/convert", handleConvert).Methods("POST")
r.HandleFunc("/status/{task_id}", handleStatus).Methods("GET")
r.HandleFunc("/download/{task_id}", handleDownload).Methods("GET")
fmt.Println("Starting server on :8080")
http.ListenAndServe(":8080", r)
}
func handleConvert(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(10 << 20) // Limit upload size to 10MB
inputFormat := r.FormValue("input_format")
outputFormat := r.FormValue("output_format")
file, _, err := r.FormFile("file")
if err != nil {
http.Error(w, "Failed to read file", http.StatusBadRequest)
return
}
defer file.Close()
tempFile, err := os.CreateTemp("uploads", "input-*."+inputFormat)
if err != nil {
http.Error(w, "Failed to save file", http.StatusInternalServerError)
return
}
defer tempFile.Close()
io.Copy(tempFile, file)
taskID := uuid.New().String()
task := ConversionTask{
TaskID: taskID,
InputFormat: inputFormat,
OutputFormat: outputFormat,
Status: "processing",
FilePath: tempFile.Name(),
}
taskStore.Store(taskID, task)
go convertFile(task)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{"task_id": taskID, "status": "processing"})
}
func convertFile(task ConversionTask) {
outputFile := fmt.Sprintf("output-%s.%s", task.TaskID, task.OutputFormat)
cmd := exec.Command("convert", task.FilePath, outputFile) // ImageMagick
err := cmd.Run()
if err != nil {
task.Status = "failed"
} else {
task.Status = "completed"
task.FilePath = outputFile
}
taskStore.Store(task.TaskID, task)
}
func handleStatus(w http.ResponseWriter, r *http.Request) {
taskID := mux.Vars(r)["task_id"]
value, ok := taskStore.Load(taskID)
if !ok {
http.Error(w, "Task not found", http.StatusNotFound)
return
}
task := value.(ConversionTask)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(task)
}
func handleDownload(w http.ResponseWriter, r *http.Request) {
taskID := mux.Vars(r)["task_id"]
value, ok := taskStore.Load(taskID)
if !ok {
http.Error(w, "Task not found", http.StatusNotFound)
return
}
task := value.(ConversionTask)
if task.Status != "completed" {
http.Error(w, "File not ready", http.StatusBadRequest)
return
}
http.ServeFile(w, r, task.FilePath)
}
Example Usage
Upload and Convert a File
curl -X POST -F "file=@input.png" -F "input_format=png" -F "output_format=jpg" http://localhost:8080/convert
Check Conversion Status
curl http://localhost:8080/status/<task_id>
Download Converted File
curl -O http://localhost:8080/download/<task_id>
Enhancements for Production
Authentication: Secure endpoints using JWT or API keys.
Persistent Storage: Use a database to store task details and file metadata.
Distributed Processing: Implement task queues (e.g., RabbitMQ) for scaling.
Logging and Monitoring: Add structured logging and integrate monitoring tools like Prometheus.
Error Handling: Enhance error messages and retry mechanisms.
Conclusion
This implementation serves as a solid foundation for building a scalable file conversion API in Go. With further enhancements, such as support for additional file formats, authentication, and optimized performance, it can evolve into a production-ready solution for various use cases.
I hope you found this article helpful! Happy coding! ๐ Thanks for reading, and see you in my next article on BuggedMind! ๐
Subscribe to my newsletter
Read articles from Ahmed Raza directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ahmed Raza
Ahmed Raza
Ahmed Raza is a versatile full-stack developer with extensive experience in building APIs through both REST and GraphQL. Skilled in Golang, he uses gqlgen to create optimized GraphQL APIs, alongside Redis for effective caching and data management. Ahmed is proficient in a wide range of technologies, including YAML, SQL, and MongoDB for data handling, as well as JavaScript, HTML, and CSS for front-end development. His technical toolkit also includes Node.js, React, Java, C, and C++, enabling him to develop comprehensive, scalable applications. Ahmed's well-rounded expertise allows him to craft high-performance solutions that address diverse and complex application needs.