func (h FileService) BuildFile(file kit.File, user kit.User, deleteDir, deleteFile bool) apperror.Error { if h.DefaultBackend == nil { return &apperror.Err{ Code: "no_default_backend", Message: "Cant build a file without a default backend.", } } filePath := file.GetTmpPath() if filePath == "" { return &apperror.Err{ Code: "no_tmp_path", Message: "You must set TmpPath on a file before building it.", Public: true, } } if file.GetBackendName() == "" { file.SetBackendName(h.DefaultBackend().Name()) } backend := h.Backend(file.GetBackendName()) if backend == nil { return &apperror.Err{ Code: "unknown_backend", Message: fmt.Sprintf("The backend %v does not exist", file.GetBackendName()), } } file.SetBackend(backend) if file.GetBucket() == "" { return &apperror.Err{ Code: "missing_bucket", Message: "Bucket must be set on the file", } } stat, err := os.Stat(filePath) if err != nil { if err == os.ErrNotExist { return &apperror.Err{ Code: "file_not_found", Message: fmt.Sprintf("File %v does not exist", filePath), } } return apperror.Wrap(err, "stat_error", fmt.Sprintf("Could not get file stats for file at %v: %v", filePath, err)) } if stat.IsDir() { return apperror.New("path_is_directory") } // Build the hash. hash, err2 := utils.BuildFileMD5Hash(filePath) if err2 != nil { return err2 } file.SetHash(hash) pathParts := strings.Split(filePath, string(os.PathSeparator)) fullName := pathParts[len(pathParts)-1] nameParts := strings.Split(fullName, ".") // Determine extension. extension := "" if len(nameParts) > 1 { extension = nameParts[len(nameParts)-1] } file.SetFullName(fullName) file.SetSize(stat.Size()) // Determine mime type. mimeType := GetMimeType(filePath) if mimeType == "" { mimeType = mime.TypeByExtension("." + extension) } file.SetMime(mimeType) if strings.HasPrefix(mimeType, "image") { file.SetIsImage(true) file.SetMediaType(MEDIA_TYPE_IMAGE) // Determine image info. imageInfo, err := GetImageInfo(filePath) if imageInfo != nil { file.SetWidth(int(imageInfo.Width)) file.SetHeight(int(imageInfo.Height)) } else { h.Registry().Logger().Warningf("Could not determine image info: %v", err) } } if strings.HasPrefix(mimeType, "video") { file.SetMediaType(MEDIA_TYPE_VIdEO) } // Store the file in the backend. backendId, writer, err2 := file.Writer(true) if err2 != nil { return apperror.Wrap(err2, "file_backend_error") } defer writer.Close() // Open file for reading. f, err := os.Open(filePath) if err != nil { return apperror.Wrap(err, "read_error", fmt.Sprintf("Could not read file at %v", filePath)) } _, err = io.Copy(writer, f) if err != nil { f.Close() return apperror.Wrap(err, "copy_to_backend_failed") } f.Close() // File is stored in backend now! file.SetBackendId(backendId) // Persist file to db. file.SetTmpPath("") if file.GetStrId() != "" { err2 = h.resource.Update(file, user) } else { err2 = h.resource.Create(file, user) } if err2 != nil { // Delete file from backend again. backend.DeleteFile(file) return apperror.Wrap(err2, "db_error", "Could not save file to database") } // Delete tmp file. if deleteFile { os.Remove(filePath) } if deleteDir { dir := strings.Join(pathParts[:len(pathParts)-1], string(os.PathSeparator)) os.RemoveAll(dir) } return nil }